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

dcast fails to cast character column when the data size is large

我正在使用 library(reshape2) 包中的 dcast 函数来转换一个简单的 table 三列

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

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

id     continent   subcontinent
 1     1           1
 2     1           1

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

id     continent   subcontinent
 1     America     Caribbean
 2     Europe      West Europe

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

我通过包含聚合函数找到了解决此问题的快速方法。它现在可以工作了,但我仍然不确定为什么 dcast 对于不同大小的数据表现不同。

dcast(df, id ~ var, value.var ='val', fun.aggregate =function(x) paste(x[1])

这可能是由重复条目引起的。

因此您可能在您的子集中无意中删除了重复的行条目。

使用具有重复条目的 DF 输出

df = data.table(id  = c(1,2,3,4,2), 
                var = c('continent','subcontinent','continent','continent','subcontinent'), 
                val = c('America','Caribbean','Africa','Europe','Caribbean'))

dcast(df, id ~ var, value.var ='val')

Aggregate function missing, defaulting to 'length'
   id continent subcontinent
1:  1         1            0
2:  2         0            2
3:  3         1            0
4:  4         1            0

Try unique()

如果重复项不重要,可能值得:

dcast(unique(df), id ~ var, value.var ='val')

   id continent subcontinent
1:  1   America           NA
2:  2        NA    Caribbean
3:  3    Africa           NA
4:  4    Europe           NA 

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

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

When variable combinations in formula doesn't identify a unique value in a cell, fun.aggregate will have to be specified, which defaults to length if unspecified.

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

所有重复项都可以通过

来识别
cols <- c("id", "var")
df[duplicated(df, by = cols) | duplicated(df, by = cols, fromLast = TRUE)][
  order(id)]
   id          var           val
1:  1 subcontinent     Caribbean
2:  1 subcontinent South America

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

为什么 unique() 不起作用

注意:这就是为什么简单地使用 unique(df) 不起作用的原因:

unique(df)
   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

不删除任何行。因此,

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

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

已删除 id == 1L 的重复项 var。因此,

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

如何查找重复行的行号

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

重复条目的行索引可以通过

找到
which(duplicated(df, by = cols))

其中 returns 5 用于示例数据集。对于 OP 的完整数据集,我怀疑

min(which(duplicated(df, by = cols))) > 1e5

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

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

使用 fun.aggregate = function(x) paste(x[1L]) 以及在 df 上应用 unique() 只是为了删除任何令人不安的重复项。重复项将被静默删除。

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

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

数据

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
   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