我在R (~200,000)条目中有一个非常大的data.table,我希望对每一行执行一个非向量化函数。这个函数需要来自这个data.table的两列的输入。一个列的值被链接到另一个列表,每个成员都包含大约1,000,000个数字。下面是一个使用mtcars的简化案例
#setup a fake list for my function call
gears <- mtcars %>% arrange(gear) %>% pull(gear) %>% unique
gear_lst <- lapply(gears, function(x){rnorm(1000000, mean = x**2, sd = x*2)}) %>% setNames(.,gears)
#make a mega data table
mega_mtcars <- sapply(mtcars, rep.int, times = 10000) %>% as.data.table
#this is the function I want to call
my_function <- function(x,y){
sum(x > gear_lst[[y]])
}
# rowwise call is low
out <- mega_mtcars %>% mutate(gear_c = as.character(gear)) %>% rowwise %>% mutate(out = my_function(mpg, gear_c))我尝试的一件事是为每个gear_lst条目添加一个嵌套的gear列,这样我就能够执行向量化的函数。但是,由于列表很大,内存无法创建这样的数据结构。
Update:@akrun提供了一些方法,我无法用我的原始mega_mtcars测试它们,因为它太大了。我将它缩小了100倍,下面是到目前为止的性能(与最初的逐行方法相比似乎没有任何改进):
#make a smaller mega_mtcars
mega_mtcars <- sapply(mtcars, rep.int, times = 100) %>% as.data.table
# use rowwise from dplyr
system.time(mega_mtcars %>% rowwise %>% mutate(out = my_function(mpg, as.character(gear))))
user system elapsed
8.086 2.860 10.941
# use Map with data.table
system.time(mega_mtcars[, out := unlist(Map(my_function, x = mpg, y = as.character(gear)))])
user system elapsed
7.843 2.815 10.654
# use dapply from collapse package
system.time(dapply(mega_mtcars[, .(mpg, gear)], MARGIN = 1, function(x) my_function(x[1], as.character(x[2]))))
user system elapsed
7.957 3.167 11.127 还有其他想法吗?
发布于 2022-01-02 18:08:31
使用data.table,可以通过对行序列进行分组来实现rowwise
library(data.table)
mega_mtcars[, out := my_function(mpg, as.character(gear)) ,
by = 1:nrow(mega_mtcars)]发布于 2022-01-02 22:12:34
对gear_lst中的值进行排序有帮助吗?
https://stackoverflow.com/questions/70557802
复制相似问题