鉴于这些数据,前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类似,很容易做到。
答案 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'))