【问题标题】:logical operators in data.table with by-groupsdata.table 中的逻辑运算符与分组
【发布时间】:2017-03-17 11:23:59
【问题描述】:

我正在尝试将逻辑运算符应用于 data.table 的列,它可以在没有 by= 组的情况下正常工作,但是使用 by= 组会发生一些奇怪的事情。我正在使用 R 3.3.1 和 data.table 1.9.6(关闭 CRAN)。

这是一个示例数据集:

library(data.table)
# x <- matrix(rnorm(10),ncol=2)
x <- structure(c(0.323618333400921, -0.103619160085676, -0.823322722581548, 
-0.0175726272468397, 2.17286179204364, 1.63465793636681, 0.258469984285221, 
-0.411622451584, 0.22594247704226, 0.114427086028551), .Dim = c(5L, 2L))

dt <- data.table(x)
dt$id <- c(1,1,1,2,2)
dt

##             V1         V2 id
## 1:  0.32361833  1.6346579  1
## 2: -0.10361916  0.2584700  1
## 3: -0.82332272 -0.4116225  1
## 4: -0.01757263  0.2259425  2
## 5:  2.17286179  0.1144271  2

假设我想知道累积最小值(即从样本开始到当前行或从 by= 组开始到当前行的每列中的最小值)是否低于零.当没有 by= 组时,我们很好:

dt[, cummin(.SD), .SDcols=1:2]
##            V1         V2
## 1:  0.3236183  1.6346579
## 2: -0.1036192  0.2584700
## 3: -0.8233227 -0.4116225
## 4: -0.8233227 -0.4116225
## 5: -0.8233227 -0.4116225

> dt[, cummin(.SD)<0, .SDcols=1:2]
##         V1    V2
## [1,] FALSE FALSE
## [2,]  TRUE FALSE
## [3,]  TRUE  TRUE
## [4,]  TRUE  TRUE
## [5,]  TRUE  TRUE

到目前为止一切顺利。我还可以使用 by= groups 计算实际的累积最小值:

dt[, cummin(.SD), by=id]
##    id          V1         V2
## 1:  1  0.32361833  1.6346579
## 2:  1 -0.10361916  0.2584700
## 3:  1 -0.82332272 -0.4116225
## 4:  2 -0.01757263  0.2259425
## 5:  2 -0.01757263  0.1144271

但是,如果我尝试像以前一样计算指标变量,输出如下:

dt[, (cummin(.SD)<0), by=id]
##     id    V1
##  1:  1 FALSE
##  2:  1  TRUE
##  3:  1  TRUE
##  4:  1 FALSE
##  5:  1 FALSE
##  6:  1  TRUE
##  7:  2  TRUE
##  8:  2  TRUE
##  9:  2 FALSE
## 10:  2 FALSE

而不是 5 个 obs 的 2 个变量。每个,我们有一个有 10 个。似乎在每个分组中,变量都堆叠在一起。我应该如何正确地做到这一点?

【问题讨论】:

  • 你可能想试试这个语法:dt[, .(cummin(V1)&lt;0,cummin(V2)&lt;0), by=id]
  • 谢谢!这样可行。不幸的是,在实际应用中,我有几千个这样的列,所以我不确定什么是处理这个问题的实用方法......
  • 我的猜测是 cummin 有一个 data.frame 方法,因此只是(cummin(dt) 适用于您的第一次尝试),而 (cummin(.SD)&lt;0) 是一个矩阵(这只是一个向量)和因此,在按组解析时,data.table 会以不同的方式处理它。

标签: r data.table


【解决方案1】:

它适用于lapply:

dt[,lapply(.SD,function(x) cummin(x)<0),by="id"]
   id    V1    V2
1:  1 FALSE FALSE
2:  1  TRUE FALSE
3:  1  TRUE  TRUE
4:  2  TRUE FALSE
5:  2  TRUE FALSE

正如 David Arenburg 所评论的,它似乎适用于 cummin(.SD),因为它是一个 data.frame,它不适用于 cummin(.SD)&lt;0,它是一个矩阵。所以另一种解决方案是将矩阵转换为 data.frame :

dt[, (as.data.frame(cummin(.SD)<0)), by=id]
   id    V1    V2
1:  1 FALSE FALSE
2:  1  TRUE FALSE
3:  1  TRUE  TRUE
4:  2  TRUE FALSE
5:  2  TRUE FALSE

【讨论】:

  • 还有(没有匿名函数)dt[, lapply(cummin(.SD), `&lt;`, 0), by = id](尽管在.SD 上使用lapply 比只使用cummin(.SD) 更好,因为它避免了矩阵转换)
【解决方案2】:

你可以试试这样的:

dt2 <- dt[, cummin(.SD), by = id]
results <- data.table(dt2[, .SD<0])
results$id <- dt$id

results
   id    V1    V2
1:  1 FALSE FALSE
2:  1  TRUE FALSE
3:  1  TRUE  TRUE
4:  2  TRUE FALSE
5:  2  TRUE FALSE

【讨论】:

    猜你喜欢
    • 2014-07-07
    • 1970-01-01
    • 2023-04-06
    • 2020-07-02
    • 1970-01-01
    • 2016-07-18
    • 2017-01-25
    相关资源
    最近更新 更多