Fac*_*ary -1 r mode bigdata lapply data.table
我在data.table,group by中汇总数据,我需要在组中获取变量的单个值.我希望这个值成为组的模式.我认为它需要是模式,因为通常一个组是8行,它将在一个值上有2行,而另外6个行将是另一个值.
这是一个简化的例子,由此:
key1 2
key1 2
key1 2
key1 8
key1 2
key1 2
key1 2
key1 8
Run Code Online (Sandbox Code Playgroud)
我要这个:
key1 2
Run Code Online (Sandbox Code Playgroud)
我在使用基础R提供的标准模式功能时遇到了麻烦,所以我在这里使用了这个解决方案: 按组划分最频繁的值(模式)
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
Run Code Online (Sandbox Code Playgroud)
它在我的小测试数据集上运行得很好,但是当我在我的实际数据集(2200万行)上运行它时,它只运行并运行和运行.我所有其他类似的 data.table操作工作得很好而且非常快,但我没有使用UDF.这是我的data.table查询的结构:
ModeCharacterColumns <- ExposureHistory[,lapply(.SD,Mode), .(Key1=Key1, Key2=Key2, ..., key7=key7, key8=key8), .SDcols=('col1','col2','col3', ..., 'col53')]
Run Code Online (Sandbox Code Playgroud)
所以我猜我的问题是我的UDF确实让事情变慢了,有没有人有任何建议我可以完成同样的目标但是更快地完成它?
谢谢大家!
编辑: 更好地表示数据:
DT <- fread("key1A key2A key3A key4A 2 2 4 s
key1A key2A key3A key4A 2 2 4 s
key1A key2A key3A key4A 8 8 8 t
key1A key2A key3A key4A 2 2 4 s
key1B key2B key3B key4B 6 6 6 v
key1B key2B key3B key4B 2 2 5 t
key1B key2B key3B key4B 2 2 5 v
key1B key2B key3B key4B 2 2 5 v")
Run Code Online (Sandbox Code Playgroud)
并且期望的结果:
result <- fread("key1A key2A key3A key4A 2 2 4 s
key1B key2B key3B key4B 2 2 5 v")
Run Code Online (Sandbox Code Playgroud)
尝试使用data.table将数据制表:
DT <- fread("key1 8
key1 2
key1 2
key1 8
key1 2
key1 2
key1 2
key1 8")
setkeyv(
DT[, .N, by = .(V1, V2)], #tabulate
c("V1", "N") #sort by N
)[, .(Mode = V2[.N]), by = V1] #most frequent value by V1
# V1 Mode
#1: key1 2
Run Code Online (Sandbox Code Playgroud)
你需要仔细考虑打破平局.我可能实际上使用for
循环将其应用于更多值列,但如果您希望我尝试,则需要提供代表性的可重现示例.
编辑:
Frank为注释中的多个值列提供了一个选项:
DT[, lapply(.SD, function(x) setDT(list(x = x))[, .N, by=x][order(-N)][1L, x]), by=V1]
Run Code Online (Sandbox Code Playgroud)
但是,我相信这会复制每个值列,这可能会减慢它的速度.