【问题标题】:r data.table avoid class discrepancy between RHS and LHSr data.table 避免 RHS 和 LHS 之间的类差异
【发布时间】:2018-08-18 11:20:11
【问题描述】:

我有一个包含一些组的数据集,我想计算每个组中满足某个条件的记录数。然后我想将结果扩展到每个组中的其余记录(即不满足条件的地方),因为我稍后会折叠表格。

我正在使用 data.table 来执行此操作,并使用 .N 函数来计算每个组中满足我条件的记录数。然后,我获取每个组中所有值的最大值,以将结果应用于每个组中的所有记录。我的数据集非常大(将近 500 万条记录)。

我不断收到以下错误:

  Error in `[.data.table`(dpart, , `:=`(clustersize4wk, max(clustersize4wk,  : 
  Type of RHS ('double') must match LHS ('integer'). To check and coerce would impact performance too much for the fastest cases. Either change the type of the target column, or coerce the RHS of := yourself (e.g. by using 1L instead of 1)

起初,我假设使用.N 会产生一个整数,而按组获取值的最大值会产生一个双精度数,但情况似乎并非如此(在下面的玩具示例中,类的结果列始终保持为整数),我无法重现该问题。

为了说明,这里是一个例子:

# Example data:

mydt <- data.table(id = c("a", "a", "b", "b", "b", "c", "c", "c", "c", "d", "d", "d"),
                   grp = c("G1", "G1", "G1", "G1", "G1", "G2", "G2", "G2", "G2", "G2", "G2", "G2"),
                   name = c("Jack", "John", "Jill", "Joe", "Jim", "Julia", "Simran", "Delia", "Aurora", "Daniele", "Joan", "Mary"),
                   sex = c("m", "m", "f", "m", "m", "f", "m", "f", "f", "f", "f", "f"), 
                   age = c(2,12,29,15,30,75,5,4,7,55,43,39), 
                   reportweek = c("201740", "201750", "201801", "201801", "201801", "201748", "201748", "201749", "201750", "201752", "201752", "201801"))

我正在计算每组中男性的数量,如下所示:

mydt[sex == "m", csize := .N, by = id]

> is.integer(mydt$csize)
[1] TRUE
> is.double(mydt$csize)
[1] FALSE

有些组不包含任何男性,因此为了避免在下一步中获得Inf,我将 NA 重新编码为 0:

mydt[ is.na(csize), csize := 0]

然后我将结果扩展到每个组中的所有成员,如下所示:

mydt[, csize := max(csize, na.rm = T), by = id] 

> is.integer(mydt$csize)
[1] TRUE
> is.double(mydt$csize)
[1] FALSE

这是错误出现在我的真实数据集中的点。如果我省略将 NA 重新编码为 0 的步骤,我可以使用示例数据重现错误;否则不是。同样使用我的真实数据集(尽管已将 NA 重新编码为 0),我仍然收到以下警告:

19: In max(clustersize4wk, na.rm = TRUE) :
  no non-missing arguments to max; returning -Inf 

我该如何解决这个问题?

我的预期输出如下:

> mydt
    id grp    name sex age reportweek csize
 1:  a  G1    Jack   m   2     201740     2
 2:  a  G1    John   m  12     201750     2
 3:  b  G1    Jill   f  29     201801     2
 4:  b  G1     Joe   m  15     201801     2
 5:  b  G1     Jim   m  30     201801     2
 6:  c  G2   Julia   f  75     201748     1
 7:  c  G2  Simran   m   5     201748     1
 8:  c  G2   Delia   f   4     201749     1
 9:  c  G2  Aurora   f   7     201750     1
10:  d  G2 Daniele   f  55     201752     0
11:  d  G2    Joan   f  43     201752     0
12:  d  G2    Mary   f  39     201801     0

【问题讨论】:

  • 似乎问题是在没有值时取最大值。例如,is.double(max(NA, na.rm=TRUE)) 返回 TRUE,因为它返回 -Inf,它表示为双精度。当没有值时你想返回什么?呐?也许csize := ifelse(sum(!is.na(csize))&gt;0, max(csize, na.rm = T), NA)?
  • 没有值时,结果应该为0(如上面id组'd'中,没有男性,csize代表该组男性的数量,所以答案应该是0 d) 组中的所有记录。
  • 打开,然后可能只是csize := max(c(0L,csize), na.rm = T)
  • 你可以做mydt[, n := mydt[sex == "m"][.SD, on=.(id), .N, by=.EACHI]$N]或者更简单..mydt[, n := sum(sex == "m"), by=id]
  • 我喜欢@Frank 解决方案的简单性,尽管在我的实际数据中并不总是可以求和(例如,在某些情况下,我想获得组内的最大日期)。

标签: r class integer data.table double


【解决方案1】:

实际的问题是csize 的数据类型。它的类型为integer。 max 返回 double 类型。

解决方法可能是:

mydt[sex == "m", csize := as.double(.N), by = id]

mydt[, csize := max(csize, 0, na.rm = TRUE), by = id]

【讨论】:

  • 谢谢你 - 我的 r 会话刚刚崩溃,但我不认为这是由于你的解决方案,因为它看起来很明智,所以我会接受这个答案并假设它会在我可以的时候工作调试我的脚本的其余部分。
  • 更新:似乎评估条件语句,例如sex == "m" 给出一个整数作为答案(然后它与 RHS 上的 .N 不兼容,因为它被 as.double(.N) 转换为双精度)。因此,对于计数,@Frank 解决方案更好,因为它避免了不满足条件的行出现空白的问题,同时不会导致 RHS 和 LHS 之间出现任何类差异:mydt[, n := sum(sex == "m"), by=id]。
  • @AmyM sex == "m" 不会在分配中发挥任何作用,这不是错误的根本原因(如 RHS ('double') must..)。您已经检查过is.integer(mydt$csize) 是TRUE。您可以尝试is.double(max(mydt$csize)) 找到它为TRUE。我的回答是帮助你理解问题并克服它。否则还有其他方法可以解决。
  • 我在上面发布更新的原因是因为在将您的解决方案应用于我的真实数据时,我得到了与以前相同的 RHS: LHS 类差异错误 - 但你是对的,我已经检查过这个并且这不应该是一个问题。我现在怀疑在处理缺失值、分组向量和条件的某些组合时会引发此错误或使 R 完全崩溃的错误 - 已发布问题 here
  • 真正的问题是,如果无法对它们执行其他数学运算,那么首先生成整数这样的向量是否有用。如果 .N 像普通函数一样工作,带有一个可选参数来返回整数或双精度,那就太好了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-18
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
  • 1970-01-01
相关资源
最近更新 更多