繁体   English   中英

在 dplyr 中使用 mutate 条件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM