【问题标题】:data.table: create new columns with lapplydata.table:使用 lapply 创建新列
【发布时间】:2013-04-07 12:50:24
【问题描述】:

我有一个 data.table 并希望对行的每个子集应用一个函数。 通常情况如下:DT[, lapply(.SD, function), by = y]

但在我的情况下,该函数不返回原子向量,而只是返回一个向量。 有没有机会做这样的事情?

library(data.table)
set.seed(9)
DT <- data.table(x1=letters[sample(x=2L,size=6,replace=TRUE)],
                 x2=letters[sample(x=2L,size=6,replace=TRUE)],
                 y=rep(1:2,3), key="y")
DT
#   x1 x2 y
#1:  a  a 1
#2:  a  b 1
#3:  a  a 1
#4:  a  a 2
#5:  a  b 2
#6:  a  a 2

DT[, lapply(.SD, table), by = y]
# Desired Result, something like this:
# x1_a x2_a x2_b
#    3    2    1
#    3    2    1

提前致谢,另外:我不介意函数的结果是否必须具有固定长度。

【问题讨论】:

  • 您希望 x1 和 x2 具有相同的级别吗?
  • @RicardoSaporta 为简单起见,假设如此。
  • 没有它会更简单。否则,需要修改级别。我是根据您如何创建 data.table 来询问的。 (即,从同一个集合中采样,但由于随机采样,并非所有值都被表示。非值应该为 0,还是应该直接忽略)?

标签: r data.table lapply


【解决方案1】:

您只需要取消列出该表,然后强制返回一个列表:

> DTCounts <- DT[, as.list(unlist(lapply(.SD, table))), by=y]
> DTCounts

   y x1.a x2.a x2.b
1: 1    3    2    1
2: 2    3    2    1



如果你不喜欢名字中的点,你可以sub他们:

> setnames(DTCounts, sub("\\.", "_", names(DTCounts)))
> DTCounts

   y x1_a x2_a x2_b
1: 1    3    2    1
2: 2    3    2    1

请注意,如果不是每个组的列中的所有值都存在
(即,如果x2=c("a", "b")y=1,但x2=c("b", "b")y=2
然后上述中断。

解决方案是在计数之前使列因子。

DT[, lapply(.SD, is.factor)]

## OR
columnsToConvert <- c("x1", "x2")  # or .. <- setdiff(names(DT), "y") 
DT <- cbind(DT[, lapply(.SD, factor), .SDcols=columnsToConvert], y=DT[, y])

【讨论】:

  • 您可能想在DT[, y] 中添加with = FALSE??或DT[, list(y)]
  • @Arun,在这种情况下不是。 DT[, "y", with=FALSE] 将产生一个data.table,相当于DT[, list(y)](减去密钥)。另一方面,DT[, y] 返回一个类似于DT$y的向量
  • 是的,但我想知道为什么要将其转换为矢量,因为那样,cbind 将强制它为data.frame。那是你要的吗? class(cbind(y=DT[, y], DT[, lapply(.SD, factor), .SDcols=columnsToConvert])) ## [1] data.frame
  • @Arun,是的,好点!我最初将y=DT[, y] 作为第二个参数,并将其向前移动以使其更明显。我忽略了对 cbind 的影响。很好的电话,谢谢。我已经编辑了答案。
  • (+1) 比我的好多了!
猜你喜欢
  • 2018-07-28
  • 2020-09-12
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 2020-11-19
  • 1970-01-01
  • 2018-11-25
  • 2020-03-12
相关资源
最近更新 更多