[英]Using mutate in dplyr with conditions
编辑:将其恢复为原始文本,以下响应基于该文本。 感谢大家的帮助,并为在大家如此慷慨地帮助我之后改变问题而道歉。
我有一个数据框,其中列出了个人、他们喝了多少酒、他们在排队的 position 以及他们是否有资格获得新饮料。
dat <- data.frame(person = c("bill", "hank", "susy", "cliff", "betty"),
total = c(3, 4, 5, 7, 8),
position = c(1, 5, 3, 2, 4),
eligible = c(0, 0, 1, 1, 1))
目标是,对于任何有资格获得新饮料的人,我们必须将他们的饮料总数、排在他们后面的人的饮料总数(例如,在第 4 个人的总数中,我们添加总数人 5 的饮料)。 对于没有资格获得新饮料的任何人,我们将保留他们的旧总数。 所需的output如下:
person total position eligible new_total
bill 3 1 0 3
hank 4 5 0 4
susy 5 3 1 13
cliff 7 2 1 12
betty 8 4 1 12
有谁知道我如何使用 R 和 dplyr 来做到这一点?
谢谢!
您可以使用 mutate 和 ifelse。 它有助于首先对列表进行排序。
dat <- dat %>%
arrange(position) %>%
mutate(new_total = ifelse(eligible, total+lead(total), total)) %>%
arrange(total)
一个选项是使用rn
创建一个序列列,按“位置” arrange
,然后在eligible
为 1 时通过添加“总”和“总”的lead
创建“新总”,并根据“RN”重新排序先前创建的列
library(dplyr)
dat %>%
mutate(rn = row_number()) %>%
arrange(position) %>%
mutate(new_total = case_when(as.logical(eligible) ~
total + lead(total), TRUE ~ total)) %>%
arrange(rn) %>%
select(-rn)
# person total position eligible new_total
#1 bill 3 1 0 3
#2 hank 4 5 0 4
#3 susy 5 3 1 13
#4 cliff 7 2 1 12
#5 betty 8 4 1 12
或使用data.table
library(data.table)
setDT(dat)[order(position), new_total := total + shift(total, type = 'lead')
][eligible == 0, new_total := total][]
# person total position eligible new_total
#1: bill 3 1 0 3
#2: hank 4 5 0 4
#3: susy 5 3 1 13
#4: cliff 7 2 1 12
#5: betty 8 4 1 12
资格已经是 0/1,因此您可以通过将下一个人的总数乘以资格(或者,如果不是那么简单,则在此处设置任何真/假条件)来使用它来为您带来好处:
dat %>% arrange(position) %>%
mutate(new_total=total+eligible*(lead(total,default=0)))
person total position eligible new_total
1 bill 3 1 0 3
2 cliff 7 2 1 12
3 susy 5 3 1 13
4 betty 8 4 1 12
5 hank 4 5 0 4
只是为了好玩,我比较了三种解决方案(尽管数据集这么小,这种比较可能不准确):
Unit: milliseconds
expr min lq mean median uq max neval
iod 2.485992 2.694608 3.535079 2.921297 3.347454 28.47935 100
brian 3.700652 4.037115 4.759614 4.268713 4.973099 16.12168 100
arkun(dplyr) 8.173740 9.117087 10.194020 9.715270 10.730906 17.32028 100
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.