当数据量很大时,dcast 无法转换字符列

Lam*_*thy 5 r dcast

我正在使用包中的dcast函数 library(reshape2)来投射一个简单的三列表格

df = data.table(id  = 1:1e6, 
             var = c('continent','subcontinent',...), 
             val = c('America','Caribbean',...)````
Run Code Online (Sandbox Code Playgroud)

bydcast(df, id ~ var, value.var ='val')并自动将值转换为计数,即

id     continent   subcontinent
 1     1           1
 2     1           1
Run Code Online (Sandbox Code Playgroud)

但是,如果我将大小减少到 10000 行,它会正确输出

id     continent   subcontinent
 1     America     Caribbean
 2     Europe      West Europe
Run Code Online (Sandbox Code Playgroud)

这是一个错误还是我需要以某种方式更改代码?请帮忙。谢谢!

Uwe*_*Uwe 7

问题不在于数据集本身的大小,而在于完整数据集中出现重复条目​​。通过从完整数据集中挑选较小的子集,有可能不包含重复项。

help("dcast", "data.table") 说:

当变量组合formula不能标识单元格中的唯一值时,fun.aggregate必须指定,length如果未指定则默认为。

如何在完整数据集中查找重复项

所有出现的重复都可以通过

cols <- c("id", "var")
df[duplicated(df, by = cols) | duplicated(df, by = cols, fromLast = TRUE)][
  order(id)]
Run Code Online (Sandbox Code Playgroud)
   id          var           val
1:  1 subcontinent     Caribbean
2:  1 subcontinent South America
Run Code Online (Sandbox Code Playgroud)

请注意,我们正在寻找重复项idvar因为这两个构成了重塑结果的单元格,即行和列。

为什么unique()不起作用

注意:这就是为什么简单地采取unique(df)行不通的解释:

unique(df)
Run Code Online (Sandbox Code Playgroud)
   id          var           val
1:  1    continent       America
2:  1 subcontinent     Caribbean
3:  2    continent        Europe
4:  2 subcontinent   West Europe
5:  1 subcontinent South America
Run Code Online (Sandbox Code Playgroud)

不删除任何行。最后,

dcast(unique(df), id ~ var, value.var = "val")
Run Code Online (Sandbox Code Playgroud)
Aggregate function missing, defaulting to 'length'
   id continent subcontinent
1:  1         1            2
2:  2         1            1
Run Code Online (Sandbox Code Playgroud)

然而

unique(df, by = cols)
Run Code Online (Sandbox Code Playgroud)
   id          var         val
1:  1    continent     America
2:  1 subcontinent   Caribbean
3:  2    continent      Europe
4:  2 subcontinent West Europe
Run Code Online (Sandbox Code Playgroud)

去掉了重复varid == 1L。最后,

dcast(unique(df, by = cols), id ~ var, value.var = "val")
Run Code Online (Sandbox Code Playgroud)
   id continent subcontinent
1:  1   America    Caribbean
2:  2    Europe  West Europe
Run Code Online (Sandbox Code Playgroud)

如何找到重复行的行号

OP 报告说该问题仅出现在完整数据集上,而不出现在第一1e5行的子集上。

可以通过以下方式找到重复条目的行索引

which(duplicated(df, by = cols))
Run Code Online (Sandbox Code Playgroud)

它返回5样本数据集。对于 OP 的完整数据集,我怀疑

min(which(duplicated(df, by = cols))) > 1e5
Run Code Online (Sandbox Code Playgroud)

为真,即前 1e5 行内没有重复项。

即使在重复条目的情况下如何创建字符列

OP自己的方式使用fun.aggregate = function(x) paste(x[1L]),以及应用unique()df仅仅着眼于消除任何干扰副本。重复项将被悄悄删除。

或者,toString()可以用作显示重复条目的聚合函数:

dcast(df, id ~ var, toString, value.var = "val")
Run Code Online (Sandbox Code Playgroud)
   id continent             subcontinent
1:  1   America Caribbean, South America
2:  2    Europe              West Europe
Run Code Online (Sandbox Code Playgroud)

数据

library(data.table)
df <- data.table(
  id  = c(1L, 1L, 2L, 2L, 1L),
  var = c("continent", "subcontinent", "continent", "subcontinent", "subcontinent"),
  val = c("America", "Caribbean", "Europe", "West Europe", "South America")
)

df
Run Code Online (Sandbox Code Playgroud)
   id          var           val
1:  1    continent       America
2:  1 subcontinent     Caribbean
3:  2    continent        Europe
4:  2 subcontinent   West Europe
5:  1 subcontinent South America
Run Code Online (Sandbox Code Playgroud)