首页 > 解决方案 > if else 命令在 data.table 中添加列

问题描述

假设我有一个 data.table 列“A”、“C”、“byvar”,有时还有“B”。我想用一个变量'byvar'来总结它,但只包括 B 如果它存在或以其他一些标准为条件。

以下似乎不起作用,有人有想法吗?

dt[, .(
A=sum(A),
if("B" %in% names(dt)) {B=mean(B)},
C=mean(C),
D=sum(A)/C
), by = .(byvar)]
             

标签: rdata.table

解决方案


试试B=ifelse("B"%in%names(dt),mean(B),NA)它会给你一个带有 NA 的列,但它可以扩展到任意标准和列名。

dt<-data.table(A=runif(100,1,100), C=runif(100,1,100), byvar=rep(letters[1:10],10))
dt[, .(
  A=sum(A),
  B=ifelse("B"%in%names(dt),mean(B),NA),
  C=mean(C),
  D=sum(A)/C
), by = .(byvar)]

在运行此程序时,我得到 100 行响应,因为其中包含原始 C 而不是新 C,因此它为您D=sum(A)/C提供C100 行,因为有 100 Cs。如果您更改对Dto的定义,sum(A)/mean(C)那么它会给出您可能想要的内容。

编辑:

J另一种方法是利用在表达式中使用花括号的能力

dt[, {checkcol='B'
  prelimreturn=list(A=sum(A),
                    C=mean(C),
                    D=sum(A)/mean(C))
  if(checkcol%in%names(dt)) prelimreturn[[checkcol]]<-mean(get(checkcol))
  prelimreturn}
, by = .(byvar)]

在这里,我设置了一个名为的辅助变量checkcol,这样我们就不会放在"B"两个地方。接下来,我们使用您知道您想要的列来制作您的初步结果。之后,我们检查是否存在任何内容,checkcol如果存在,我们将该列添加到我们现有的列表中。然后花括号中的最后一行data.table显示的是我们的prelimresult列表,它可能有也可能没有“B”列。你也可以相当广泛地扩展这种方法。


推荐阅读