【问题标题】:Undocumented error in dcast.data.tabledcast.data.table 中未记录的错误
【发布时间】:2014-06-11 00:02:18
【问题描述】:

(这是之前在data-table-help mailing list 上发布的,但是已经有几个星期没有评论了,我做了更多的尝试来调试它。)

我遇到了一个奇怪的错误,互联网搜索只出现在data.table 的提交日志中:

# Error in dcast.data.table(test.table, as.formula(paste(class.col, "+",  : 
#   retFirst must be integer vector the same length as nrow(i)

这是在我通过随机重采样Trial 替换的data.table 上运行先前测试的工作dcast.data.table 表达式时出现的。有问题的部分是这样的:

dcast.data.table(test.table, 
                 Class + Time + Trial ~ Channel,
                 value.var = "Voltage",
                 fun.aggregate=identity)

输入表中几乎重复的行似乎令人窒息(即,无论表中是否存在id 列,错误都是相同的):

test.table <- structure(list(Trial = c(1169L, 1169L), Sample = c(155L, 155L
), Class = c(1L, 1L), Subject = structure(c(13L, 13L), .Label = c("s01", 
"s02", "s03", "s04", "s05", "s06", "s07", "s08", "s09", "s10", 
"s11", "s12", "s13"), class = "factor"), Channel = c(1L, 1L), 
    Voltage = structure(c(-0.992322316444497, -0.992322316444497
    ), "`scaled:center`" = -6.23438399446429e-16, "`scaled:scale`" = 1), 
    Time = c(201.149466192171, 201.149466192171), Baseline = c(0.688151312347969, 
    0.688151312347969), id = 1:2), .Names = c("Trial", "Sample", 
"Class", "Subject", "Channel", "Voltage", "Time", "Baseline", 
"id"), class = c("data.table", "data.frame"), row.names = c(NA, 
-2L), sorted = "id")    

test.table
#    Trial Sample Class Subject Channel    Voltage     Time  Baseline id
# 1:  1169    155     1     s13       1 -0.9923223 201.1495 0.6881513  1
# 2:  1169    155     1     s13       1 -0.9923223 201.1495 0.6881513  2
dcast.data.table(test.table, 
                  Class + Time + Trial ~ Channel,
                  value.var = "Voltage",
                  fun.aggregate=identity)
# Error in dcast.data.table(test.table, Class + Time + Trial ~ Channel,  : 
#   retFirst must be integer vector the same length as nrow(i)

更改 dcast 公式中的单个列会接近我正在寻找的输出:

test.table[2,Trial:=1170]
dcast.data.table(test.table, 
                  Class + Time + Trial ~ Channel,
                  value.var = "Voltage",
                  fun.aggregate=identity)
#    Class     Time Trial          1
# 1:     1 201.1495  1169 -0.9923223
# 2:     1 201.1495  1170 -0.9923223

data.table 有什么问题?我尝试更改键并弄乱公式术语的顺序只是为了查看,因为我不理解错误,但这不起作用。

如果我用来自reshape2 的常规dcast 替换函数调用,我会得到一个看似无关的错误:

# Error in vapply(indices, fun, .default) : values must be length 0, but FUN(X[[29]]) result is length 1

此时在我的代码中,我不在乎 Trial 的值是否正确,因此我可以通过在公式中将其替换为 id 来解决此问题,但我对更通用的或强大的解决方案。

【问题讨论】:

  • 如果您的示例是 reproducible,将会很有帮助。您没有包含示例数据,因此我们可以准确地运行您的代码并遇到相同的错误。
  • 我同意,并且我在问题中提到我想知道错误的含义,以便我知道如何以简洁的方式重现它,而不是用大量(可能不相关的)代码。
  • 我不会说这些错误是不相关的,两者似乎都表明存在返回值不是它“应该”的长度的情况。将需要一个可重现的示例。尝试找到发生错误的数据的最小子集,然后使用 gist.github 或类似文件来托管数据。
  • 我将其缩小到相同行的 dcast 并设法得到一个工作示例。

标签: r data.table reshape2 resampling


【解决方案1】:

更新:在 v1.9.3 的 commit 1253 中修复。来自NEWS

  • dcast.data.table 在指定 fun.aggregate 时提供更好的错误消息,但它返回长度!= 1。关闭 git #693。感谢 Trevor Alexander 报告here on SO

我同意错误消息应该更有助于理解问题,它通常位于 data.table 中。这只是我没有预见到的情况。

如果您可以将问题here 提交为错误,我会在有时间时修复它。


但是,对我来说,您的问题似乎是微不足道的 RTFM。来自?dcast.data.table

fun.aggregate - 数据是否应该在投射前汇总?如果公式没有为每个单元格识别单个观察值,则聚合默认为带有消息的长度。

DETAILS 部分:"... fun.aggregate 必须使用。聚合函数应将向量作为输入并返回单个值(或长度一)作为输出。” ...

在您的示例中,您的公式的 LHS 生成两个相同的行,这意味着必须使用 fun.aggregate - 如果您使用其中之一,则默认为 length(就像 reshape2:::dcast 一样)。你已经使用了identity,它只会返回值。所以它返回了函数不喜欢的Voltage 的两个值。

错误信息应该是这样的:

错误:fun.aggregate 应为每个唯一组(来自公式的 LHS)返回长度为 1 的向量,但为组返回 length=2

或类似的东西。随意提出更好/更清晰的错误消息。


PS:我不明白你所说的几乎重复是什么意思。

identical(test.table[1, list(Class, Time, Trial)], 
          test.table[2, list(Class, Time, Trial)])
# [1] TRUE

如果您在 LHS 上使用 id 列,那么您应该能够获得所需的结果,因为您现在可以唯一地标识行...

dcast.data.table(test.table, 
             Class + Time + Trial ~ Channel + id,
             value.var = "Voltage",
             fun.aggregate=identity)

#    Class     Time Trial        1_1        1_2
# 1:     1 201.1495  1169 -0.9923223 -0.9923223

该函数仅考虑公式 LHS 中给出的列来确定是否存在/不是唯一行,而不是您的实际输入数据是否具有唯一行(如果这是混淆的话)。


回答 OP 的第二条评论:

目前获得结果(没有错误)的唯一方法是您的函数返回一个列表:

dcast.data.table(test.table, 
             Class + Time + Trial ~ Channel,
             value.var = "Voltage",
             fun.aggregate=list)
#    Class     Time Trial                     1
# 1:     1 201.1495  1169 -0.9923223,-0.9923223

然后你可以检查列的长度是否都是 1,如果是,则取消列出。

【讨论】:

  • 我将编辑问题以使其更清楚;对于那个很抱歉。我对dcast.data.table行为 绝对没有问题,而且这个错误并不令人讨厌,只是令人困惑。我所说的近乎重复的意思是 input 表不包含重复项(当给定唯一 ID 时,就像我在 dput 中所做的那样),但我给它的公式会导致非唯一行被生成。当我回到两个月前编写和测试的函数内部时,这些微妙之处就消失了,很快就忘记了它是如何工作的:)我认为你提出的错误消息非常适合这个。
  • 我在 github 上提交了问题。对于id 专栏,我也同意您的解决方法——这就是我今天使用的方法(见问题的结尾),但这有点不令人满意,因为它必须根据输入的结构进行处理;如果有某种方式来“强制唯一性”以一种不会对输出结构产生太大影响的方式,那就太好了。
猜你喜欢
  • 1970-01-01
  • 2013-06-12
  • 2013-01-30
  • 1970-01-01
  • 2019-11-11
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 2020-02-28
相关资源
最近更新 更多