R列在另一列中找到的聚合列

时间:2017-11-20 21:23:34

标签: r sum data.table

鉴于这些数据,前4列(rowid,order,line,special),我需要创建一个列,numSpecial如下:

rowid   order    line    special    numSpecial
1       A        01      X          1
2       B        01                 0
3       B        02      X          2
4       B        03      X          2
5       C        01      X          1
6       C        02                 0

其中numSpecial是通过将每个特殊订单的次数(值= X)相加来确定的,因为订单行本身是特殊的,否则为0。

我首先尝试添加一个简单的concats" order'用' X',称之为orderX,看起来像:

orderX
AX
BX
BX
BX
CX
CX

然后做一个订单和&特别在orderx:

df$numSpecial <- sum(paste(order, special, sep = "") %in% orderx)

但是这不起作用,它返回每个订单的所有行的结果总和:

numSpecial
4
4
4
4
4
4

然后我尝试了as.data.table,但我没有得到预期的结果:

as.data.table(mydf)[, numSpecial := sum(paste(order, special, sep = "") %in% orderx), by = rowid]

然而,每行只返回1而不是总和:

numSpecial
1
0
1
1
1
0

我在哪里出错?我不应该创建那个我想不到的orderX专栏,但我无法弄清楚如何正确计算这个数量。它与excel中的countif类似,很容易做到。

4 个答案:

答案 0 :(得分:2)

可能有几种方法,但你可以将它乘以"X"的TRUE / FALSE标志:

dat[, numSpecial := sum(special == "X") * (special == "X"), by=order]
dat

#   rowid order line special numSpecial
#1:     1     A    1       X          1
#2:     2     B    1                  0
#3:     3     B    2       X          2
#4:     4     B    3       X          2
#5:     5     C    1       X          1
#6:     6     C    2                  0

你也可以这样做:

dat[, numSpecial := 0L][special == "X", numSpecial := .N, by=order]

dat的位置:

library(data.table)
dat <- structure(list(rowid = 1:6, order = c("A", "B", "B", "B", "C", 
"C"), line = c(1L, 1L, 2L, 3L, 1L, 2L), special = c("X", "", 
"X", "X", "X", "")), .Names = c("rowid", "order", "line", "special"
), row.names = c(NA, -6L), class = "data.frame")
setDT(dat)

答案 1 :(得分:1)

您可以将ave与虚拟变量一起使用(仅填充1 s):

df$numSpecial <- ifelse(df$special == "X", ave(rep(1,nrow(df)), df$order, df$special, FUN = length), 0)

 df
#  rowid order line special numSpecial
#1     1     A    1       X          1
#2     2     B    1                  0
#3     3     B    2       X          2
#4     4     B    3       X          2
#5     5     C    1       X          1
#6     6     C    2                  0

注意我在没有numSpecial列的情况下读取了您的数据。

答案 2 :(得分:1)

使用dplyr包:

library(dplyr)

df %>% group_by(order) %>% 
  mutate(numSpecial = ifelse(special=="X", sum(special=="X"), 0))
  rowid  order special numSpecial
1     1      A       X          1
2     2      B                  0
3     3      B       X          2
4     4      B       X          2
5     5      C       X          1
6     6      C                  0

答案 3 :(得分:0)

仅使用基数R的另一个选项是使用聚合:

# Your data
df <- data.frame(rowid = 1:6, order = c("A", "B", "B", "B", "C", "C"), special = c("X", "", "X", "X", "X", ""))

# Make the counts    
dat <- with(df,aggregate(x=list(answer=special),by=list(order=order,special=special),FUN=function(x) sum(x=="X")))

# Merge back to original dataset:
dat.fin <- merge(df,dat,by=c('order','special'))