【问题标题】:Column in the j-expression of a data.table (with/without a by statement)data.table 的 j 表达式中的列(带/不带 by 语句)
【发布时间】:2014-04-15 18:07:41
【问题描述】:

这里有两个人为但我希望我的问题的教学示例。

1) 运行此代码时:

> dat0 <- data.frame(A=c("a","a","b"), B="")
> data.table(dat0)[, lapply(.SD, function(x) length(A)) , by = "A"]
   A B
1: a 1
2: b 1

我期待输出

   A B
1: a 2
2: b 1

(类似于plyr::ddply(dat0, .(A), nrow))。

更新问题 1)

让我举一个不那么人为的例子。考虑以下数据框:

dat0 <- data.frame(A=c("a","a","b"), x=c(1,2,3), y=c(9,8,7))
> dat0
  A x y
1 a 1 9
2 a 2 8
3 b 3 7

使用plyr包,我通过A的每个值得到xy的方法如下:

> ddply(dat0, .(A), summarise, x=mean(x), y=mean(y))
  A   x   y
1 a 1.5 8.5
2 b 3.0 7.0

非常好。现在想象另一个变量H 和以下计算:

dat0 <- data.frame(A=c("a","a","b"), H=c(0,1,-1), x=c(1,2,3), y=c(9,8,7))
> ddply(dat0, .(A), summarise, x=mean(x)^mean(H), y=mean(y)^mean(H))
  A         x         y
1 a 1.2247449 2.9154759
2 b 0.3333333 0.1428571

也很好。 但是现在,假设您要计算大量变量x mean(x)^mean(H)。那我就不想打字了:

ddply(dat0, .(A), summarise, a=mean(a)^mean(H), b=mean(b)^mean(H), c=mean(c)^mean(H), d=mean(d)^mean(H), ...........)

所以我的想法是尝试:

flipcols <- my_selected_columns # c("a", "b", "c", "d", ....)
data.table(dat0)[, lapply(.SD, function(x) mean(x)^mean(H)), by = "A", .SDcols = flipcols]

但这不起作用,因为function(x) mean(x)^mean(H) 中的H 没有按我预期的那样处理!我也无法使其与plyr::colwise 一起使用。

2) 运行此代码时:

> dat0 <- data.frame(A=c("a","a","b"), B=1:3, c=0)
> data.table(dat0)[, lapply(.SD, function(x) B), .SDcols="c"]
Error in ..FUN(c) : object 'B' not found

我预计它会起作用并生成:

   c
1: 1 
2: 2 
3: 3 

那么有没有办法在转换中使用原始 data.table 的列?

【问题讨论】:

  • 第二个例子你想做什么?将 B 的值赋给 c??
  • @RandyLai 当然,不。这个例子是人为的。问题是function(x) B 涉及B 这是数据框的一列,你可以想象你想要的函数而不是这个愚蠢的函数。
  • 但是lapply适用于子集的列,为什么函数内部有B?请参阅我的答案进行比较。
  • @RandyLai 请看第一题更新
  • 您对问题 (1) 的更新归结为您的 (2)。

标签: r data.table plyr


【解决方案1】:

1) 使用.N。分组变量 A 的长度为 1,因为每个组只有一个 A 值(这是根据分组含义的定义):

dt <- data.table(A=c("a","a","b"), B="")
dt[, .N, by = A]
#   A N
#1: a 2
#2: b 1

(更新 1) 这与 2)相同。一种解决方法是不使用.SDcols

dt = data.table(A=c("a","a","b"), H=c(0,1,-1), x=c(1,2,3), y=c(9,8,7))
dt[, lapply(.SD[, !"H"], function(x) mean(x) ^ mean(H)), by = A]
#   A         x         y
#1: a 1.2247449 2.9154759
#2: b 0.3333333 0.1428571

2) 这是以前报告过的错误:https://r-forge.r-project.org/tracker/index.php?func=detail&aid=5222&group_id=240&atid=975

【讨论】:

  • (1) 不是任何一个恕我直言的理想功能。 Bug #5191 是此功能的产物。我不认为by 变量应该掩盖x 中的原始列。这仍在讨论中。
  • 谢谢艾迪。但我的问题是一个概念性的问题:这是一个人为的例子,我的问题是关于如何在一般的函数中使用列,而不是针对这个特定的例子。
  • @Arun 嗯,我认为这个错误是关于为复杂的表达式屏蔽列 - 我不确定我明白为什么你想要像这样的简单表达式中的完整列
  • @StéphaneLaurent 也许你可以举一个不同的例子 - 我真的不知道你想要什么 atm - 一般来说 - 只需使用列(大多数时候你不需要@987654331 @) - 我假设您遇到了更具体的问题。
  • @eddi,最简单的原因是已经有一个变量.BY 允许访问分组变量值。那么为什么要把x's 列搞砸呢?从您的 dt 尝试:dt[, A, by=list(A)]dt[, A, by=list(C=A)] - 这只是令人困惑。
【解决方案2】:

我不知道我是否理解正确。

1)

library(data.table)
dat0 <- data.frame(A=c("a","a","b"), B="")
data.table(dat0)[, list(l= nrow(.SD)) , by = "A"]

结果:

   A l
1: a 2
2: b 1

2)

dat0 <- data.frame(A=c("a","a","b"), B=1:3, c=0)
data.table(dat0)[, list(c=unlist(.SD)), .SDcols= "B"]

结果:

   c
1: 1
2: 2
3: 3

1')

编辑:我把-1改成了mycols

dat0 <- data.frame(A=c("a","a","b"), H=c(0,1,-1), x=c(1,2,3), y=c(9,8,7))

data.table(dat0)[, lapply(.SD, function(x) mean(x)^mean(H)), by = "A", .SDcols = c("x", "y")]

结果:

   A         u         v
1: a 1.2247449 2.9154759
2: b 0.3333333 0.1428571

请注意,如果数据量很大,mean(H) 会被计算多次,很浪费。在这种情况下,我们可以使用{muH = mean(H); lapply(.SD, function(x) mean(x)^muH)} 来节省计算;不过,上面的内容更具可读性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多