我想知道每个变量在每个组中的变化次数,然后为所有组添加结果。
我发现了这种方式:
mi[,lapply(.SD, function(x) sum(x != shift(x),
na.rm=T) ), by = ID][,-1][,lapply(.SD,sum, na.rm=T)]
它有效,它会产生正确的结果,但在我的大型数据表中它确实很慢。 我想在同一个lapply中做两个操作(或者更快更紧凑的东西),但第一个是由group完成的,第二个不是。
它可以用更简单的方式编写(也许并不总是)
mi[,lapply(.SD, function(x) sum(x != shift(x),
na.rm=T) )] [,-1]-mi[,length(unique(ID))]+1
但它仍然很慢,需要大量记忆。
还有其他想法吗?
我也尝试过差异而不是移位,但它变得更加困难。
这里有一个虚拟的例子:
mi <- data.table(ID=rep(1:3,each=4) , year=rep(1:4, times=3),
VREP=rep(1:3,each=4) , VDI=rep(1:4, times=3), RAN=sample(12))
mi <- rbind(mi, data.table(4,1,1,1,0), use.names=F)
基准测试的典范
mi <- as.data.table(matrix(sample(0:100,10000000,
replace=T), nrow=100000, ncol=100))
mi[,ID := rep(1:1000,each=100)]
我的问题是真正的数据集要大得多,它在内存大小的限制内,然后我配置了R以便能够使用页面文件使用更多内存,并且它使许多操作变慢。 我知道我可以分割文件并再次加入它,但有时会使事情变得更加困难,或者某些操作无法拆分。
答案 0 :(得分:2)
您的第二种方法产生的结果不正确,因此不是一个公平的比较点。这是alexis_laz建议的优化版本:
setorder(mi, ID)
setDT(Map(`!=`, mi, shift(mi)))[,
lapply(lapply(.SD, `&`, !ID), sum, na.rm = T), .SDcols = -"ID"]
# year VREP VDI RAN
#1: 9 0 9 9
在更大的样本上:
setorder(mi, ID)
microbenchmark(method1(), alexis_laz(), eddi(), times = 5)
#Unit: milliseconds
# expr min lq mean median uq max neval
# method1() 7336.1830 7510.9543 7932.0476 8150.3197 8207.2181 8455.563 5
# alexis_laz() 1350.0338 1492.3793 1509.0790 1492.5426 1577.3318 1633.107 5
# eddi() 400.3999 475.6908 494.5805 504.6163 524.2077 567.988 5