разница в скорости процесса с dplyr - PullRequest
2 голосов
/ 11 апреля 2020

я написал функцию с простым для l oop в R через некоторое время, когда кто-то предложил мне другой способ сделать то же самое, но с dplyr, и после того, как я попробовал, я увидел сильную разницу во времени запустить мой скрипт (- 1 с!). Мне интересно, откуда взялась эта огромная разница во времени. dplyr просто более оптимизирован? dplyr компилируется таким образом, чтобы ускорить процесс? я не знаю

моя первоначальная функция

key.rythm <- function(key, data) {
  ## Un data frame vide pour recevoir les resultats
  results <-
    data.frame(
      "down.time" = numeric(),
      "duration" = numeric(),
      "touche" = factor()
    )
  down.time <- NULL

  ## On est oblige de passer par une boucle pour parser ligne par ligne
  for (i in 1:nrow(data)) {

    if (data[i, "K.TOUCHE"] != key)
      next

    ## Pour la bonne cle, si l'on rencontre un down, le stocker
    ##(ainsi, si l'on rencontre deux down de suite, sans up entre les deux,
    ##le premier sera effaee et seul le second comptera)
    if (data$K.EVENEMENT[i] == "Key Down") {
      down.time <- data$K.TEMPS[i]

    }  else {

      ## verifier si l'on a bien eu un down precedemment
      if (is.null(down.time)) {
        duration <- NA
        down.time <- NA
      } else{
        ## Calculer la duree entre down et up
        duration <- data$K.TEMPS[i] - down.time

      }

      ligne <- c(down.time, duration)
      results <- rbind (results, ligne)
      ## vider le down (en cas de deux up consecutifs, au cas ou)
      down.time <- NULL
    }

  }

  # 0 est considere comme FAUX on assigne que s'il y as des lignes
  if (nrow(results)){
    results$touche <- key
  }
  names (results) <- c ("down.time", "duration", "touche")
  return(results)
}

и способ dplyr

tmp<-group_by(filter (data,K.EVENEMENT  == "Key Up"), K.TOUCHE)$K.TEMPS - group_by(filter (data,K.EVENEMENT  == "Key Down"), K.TOUCHE)$K.TEMPS

Ответы [ 2 ]

1 голос
/ 11 апреля 2020

Это не полный ответ, а расширенный комментарий. Отказ от ответственности, я часто использую dplyr et c для манипулирования данными.

Я заметил, что вы перебираете каждый элемент в вашем столбце и медленно добавляете результат в вектор. Это проблематично c, потому что находится под выращиванием объекта и не может векторизовать .

Не совсем уверен, каков ваш предполагаемый вывод из вашего кода, и я делаю предположение ниже, рассматривая вашу функцию dplyr. Рассмотрим ниже, где вы можете реализовать те же результаты, используя base R и dplyr:

library(microbenchmark)
library(dplyr)
set.seed(111)

data = data.frame(K.EVENEMENT=rep(c("Key Up","Key Down"),each=500),
K.TEMPS = rnorm(1000),K.TOUCHE=rep(letters[1:2],500))
data$K.EVENEMENT = factor(data$K.EVENEMENT,levels=c("Key Up","Key Down"))

dplyr_f = function(data){
group_by(filter (data,K.EVENEMENT  == "Key Up"), K.TOUCHE)$K.TEMPS - group_by(filter (data,K.EVENEMENT  == "Key Down"), K.TOUCHE)$K.TEMPS
}

spl_red = function(data)Reduce("-",split(data$K.TEMPS,data$K.EVENEMENT))

Глядя на вашу функцию dplyr, второй член в group_by по сути бесполезен, потому что он не упорядочивает или ничего не делает, поэтому мы можем упростить функцию до:

dplyr_nu = function(data){
filter(data,K.EVENEMENT  == "Key Up")$K.TEMPS - filter (data,K.EVENEMENT  == "Key Down")$K.TEMPS
}

all.equal(dplyr_nu(data),dplyr_f(data),spl_red(data))
1] TRUE

Мы можем посмотреть на скорость:

microbenchmark(dplyr_f(data),dplyr_nu(data),spl_red(data))

           expr      min        lq       mean    median        uq      max
  dplyr_f(data) 1466.180 1560.4510 1740.33763 1636.9685 1864.2175 2897.748
 dplyr_nu(data)  812.984  862.0530  996.36581  898.6775 1051.7215 4561.831
  spl_red(data)   30.941   41.2335   66.42083   46.8800   53.0955 1867.247
 neval cld
   100   c
   100  b 
   100 a  

Я думаю, что ваша функция может быть как-то упрощена с помощью некоторого упорядочения или простого разделения и уменьшения. Может быть, есть более сложное использование для dplyr downstream, выше это просто для здоровой дискуссии.

1 голос
/ 11 апреля 2020

Конечно, вы никогда не должны писать все oop самостоятельно через data.frame. Существует множество пакетов и функций, которые вы можете использовать для манипулирования данными в R.

Я вижу, что вы находитесь только в начале вашего R путешествия. Это чудесное приключение, мой друг.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...