Правильное использование na.approx в data.table и pipe - PullRequest
0 голосов
/ 19 сентября 2018

Я очень плохо знаком с data.table и хотел бы попробовать его, чтобы увидеть, ускоряет ли он мой анализ.В основном я использую knitr для компиляции .rnw файлов (которые я собираю много раз в час, поэтому я хочу, чтобы это было как можно быстрее).

Я разместил образец ниже, и этоno означает вопрос сравнения agianst data.table и data.frame.Я хотел бы знать, если мой код ниже, что это должно быть.

Я в основном объединяю два data.tables и затем необходимо линейно аппроксимировать, используя na.approx пропущенные NA значения.Я использовал Введение в виньетку data.table из CRAN и СОЕДИНЕНИЕ данных в R с использованием data.table из R-Pubs.

Код, который я использую ниже, приводит к результатамв моей лучшей попытке использовать data.table метод, занимающий много времени (в общем, я тоже добавил только ссылку на другой код).

Кроме того, если кто-нибудь знает, есть ли способ передачи в na.approx()в цепочку и по-прежнему иметь вывод в виде data.frame, что будет оценено.Обратите внимание на строку df_merged = as.data.frame(df_merged), от которой я хотел бы избавиться, если это возможно!

Любой вклад очень важен, спасибо!

library(data.table)
library(zoo)
library(dplyr)

dt_function_test = function() {
    set.seed(123)
    # data.table
    dt_random = data.table(vals = runif(1E5, 0, 500))
    dt_na = data.table(vals = c(0, 250, 500),
                       ref1 = c(0.33, 0.45, 0.78),
                       ref2 = c(0.12, 0.79, 1))

    dt_merged = merge(dt_random[],
                      dt_na[],
                      all = TRUE)

    dt_merged = dt_merged[, lapply(.SD,
                                   na.approx),
                          by = vals]
}


df_function_test = function() {
    set.seed(123)
    # data.frame
    df_random = data.frame(vals = runif(1E5, 0, 500))
    df_na = data.frame(vals = c(0, 250, 500),
                       ref1 = c(0.33, 0.45, 0.78),
                       ref2 = c(0.12, 0.79, 1))

    df_merged = full_join(df_random,
                          df_na) %>% 
        na.approx

    df_merged = as.data.frame(df_merged)
}

print(system.time(dt_function_test()))
#  user  system elapsed 
# 11.42    0.00   11.46 

print(system.time(df_function_test()))
# Joining, by = "vals"
#    user  system elapsed  
#    0.05    0.05    0.10 

1 Ответ

0 голосов
/ 19 сентября 2018

Вот несколько возможных реализаций с использованием data.table, который выполняет zoo::na.approx для столбцов ref* (обратите внимание, что также использовался больший набор данных):

library(data.table)
library(zoo)

dt_function_test_0 = function() {
    set.seed(123)
    # data.table
    dt_random = data.table(vals = runif(1e7, 0, 500))
    dt_na = data.table(vals = c(0, 250, 500),
        ref1 = c(0.33, 0.45, 0.78),
        ref2 = c(0.12, 0.79, 1))

    cols <- c("ref1", "ref2")

    ##Version 0
    merge(dt_random, dt_na, all=TRUE)[, lapply(.SD, na.approx)]
}


dt_function_test_1 = function() {
    set.seed(123)
    # data.table
    dt_random = data.table(vals = runif(1e7, 0, 500))
    dt_na = data.table(vals = c(0, 250, 500),
        ref1 = c(0.33, 0.45, 0.78),
        ref2 = c(0.12, 0.79, 1))

    cols <- c("ref1", "ref2")

    ##Version 1: using update by reference
    merge(dt_random, dt_na, all = TRUE)[, 
        (cols) := lapply(.SD, na.approx), .SDcols=cols]
}


dt_function_test_2 = function() {
    set.seed(123)
    # data.table
    dt_random = data.table(vals = runif(1e7, 0, 500))
    dt_na = data.table(vals = c(0, 250, 500),
        ref1 = c(0.33, 0.45, 0.78),
        ref2 = c(0.12, 0.79, 1))

    cols <- c("ref1", "ref2")
    ##Version 2: using set
    dt_merged <- merge(dt_random, dt_na, all = TRUE)
    for (x in cols)
        set(dt_merged, j=x, value=na.approx(dt_merged[[x]]))
    dt_merged
}

выход синхронизации:

> system.time(dt_function_test_0())
   user  system elapsed 
   5.44    1.90    6.96 

> system.time(dt_function_test_1())
   user  system elapsed 
   3.55    1.30    4.41 

> system.time(dt_function_test_2())
   user  system elapsed 
   3.78    1.19    4.52
...