我有以下data.table(它更大,但显示了这个结构)
library(data.table)
dt = data.table(first_column = c("A", "B", "B", "B", "C", "A", "A", "A", "D", "B", "A", "A"), second_column =c(0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0))
> dt
first_column second_column
1: A 0
2: B 1
3: B 1
4: B 1
5: C 0
6: A 0
7: A 0
8: A 1
9: D 1
10: B 1
11: A 1
12: A 0
....
结果data.table应如下所示:
first_column second_column identity percent
0 A 0 0 0
1 B 1 AB 1.0
2 B 1 AB 1.0
3 B 1 AB 1.0
4 C 0 0 0
5 A 0 0 0
6 A 0 0 0
7 A 1 mixed 0.75 # 3/4, 3-AB, 4-total
8 D 1 mixed 0.75
9 B 1 mixed 0.75
10 A 1 mixed 0.75
11 A 0 0 0
....
列first_column
对于每一行A,B,C和D.在第二列中,有一个表示一组值的二进制标签。所有1的连续分组都是唯一的“组”,例如第1-3行是一组,第7-10行是另一组。
我想通过“AB”(该组仅由A或B组成),“CD”(该组仅由C或D组成)或“标记”这些组中的每一组。混合“(如果有混合物,例如所有B和一个C)。知道“如何”混合这些分组中的一些百分比,即AB在总标签中的百分比也是有用的。如果它只是A或B,则标识应为AB。如果它只是C或D,则标识应为CD。它是A,B,C和/或D的混合物,然后混合。百分比是(AB行数#)/(总行数#)
对于identity
列,我怀疑可以使用ifelse()
语句,例如。
dt$identity = ifelse( ((dt$second_column == 1) & (dt$first_column == "A") & (dt$first_column == "B") & (dt$first_column != "C") & (dt$first_column != "D")), "AB", 0)
dt$identity = ifelse( ((dt$second_column == 1) & (dt$identity != "AB") & (dt$first_column == "C") & (dt$first_column == "D") & (dt$first_column != "A") & (dt$first_column != "B")), "CD", 0)
但是我在定义“混合案例”时陷入了逻辑ifelse()
困难。我也完全不确定如何衡量AB /所有行的百分比。
答案 0 :(得分:3)
您可以使用rleid
和data.table
来获得所需内容。我使用rleid
获取分组变量,然后根据您对每个组的条件创建标识和百分比变量。感谢@DavidArenburg的建议!
dt[,c("identity", "percent") := list(if(all(first_column == "A") | all(first_column == "B")) "AB"
else if (all(first_column == "C") | all(first_column == "D")) "CD"
else "mixed", sum(first_column %in% c("A","B")) / .N), by = rleid(second_column)]
dt[second_column==0, c("identity","percent") := list("0", 0)]
dt
# first_column second_column identity percent
#1: A 0 0 0.00
#2: B 1 AB 1.00
#3: B 1 AB 1.00
#4: B 1 AB 1.00
#5: C 0 0 0.00
#6: A 0 0 0.00
#7: A 0 0 0.00
#8: A 1 mixed 0.75
#9: D 1 mixed 0.75
#10: B 1 mixed 0.75
#11: A 1 mixed 0.75
#12: A 0 0 0.00
你可以将这些电话联系起来,但我不是为了便于阅读。