繁体   English   中英

使用dplyr标记组中列的两个值之间的行

[英]Flag rows between two values of a column in a group using dplyr

我有如下的虚拟数据

df = data.frame(name = c(rep("Anna",8),rep("Jenny",7)),
                id = c(100,100,100,100,100,100,100,100,250,250,250,250,250,250,250),
                time = c("t2","t3","t5","t1","t7","t2","t1","t5","t1","t2","t6","t2","t8","t6","t5"),                stringsAsFactors = F)

> df
    name  id time
1   Anna 100   t2
2   Anna 100   t3
3   Anna 100   t5
4   Anna 100   t1
5   Anna 100   t7
6   Anna 100   t2
7   Anna 100   t1
8   Anna 100   t5
9  Jenny 250   t1
10 Jenny 250   t2
11 Jenny 250   t6
12 Jenny 250   t2
13 Jenny 250   t8
14 Jenny 250   t6
15 Jenny 250   t5

我的预期输出是,对于每个id组,我想使用time变量来flag t2t5之间(包括t2t5)的值-每个组中都会有多种情况,并且代码应能够排除某些破损情况,例如下面的例子

 > df
    name  id time Flag
1   Anna 100   t2    1
2   Anna 100   t3    1
3   Anna 100   t5    1
4   Anna 100   t1    0
5   Anna 100   t7    0
6   Anna 100   t2    1
7   Anna 100   t1    1
8   Anna 100   t5    1
9  Jenny 250   t1    0
10 Jenny 250   t2    0
11 Jenny 250   t6    0
12 Jenny 250   t2    1
13 Jenny 250   t8    1
14 Jenny 250   t6    1
15 Jenny 250   t5    1

我要求使用dplyr()模式,因为我将来可以添加更多分组变量以实现可伸缩性。 我搜索了如何在dplyr函数中使用which() ,但没有得到太多结果,我在这里找到了一个等效的python 使用Python获取列的两个值之间的行

Edit1:每个组中有多个t2-t5部分需要标记。 感谢@ronak提出来

提前致谢

应该有一个更好的选择,但这可行

library(tidyverse)

df %>%
  group_by(name) %>%
  mutate(flag  = +(row_number() %in% which(time == "t2"):which(time == "t5")))


#  name     id time   flag
#  <chr> <dbl> <chr> <dbl>
#1 Anna    100 t2        1
#2 Anna    100 t3        1
#3 Anna    100 t5        1
#4 Jenny   250 t1        0
#5 Jenny   250 t2        1
#6 Jenny   250 t3        1
#7 Jenny   250 t4        1
#8 Jenny   250 t5        1

假设每个组中只有一个“ t2”和“ t5”。

使用基本ave逻辑相同

as.numeric(with(df, ave(time, name, FUN = function(x) 
      +(1:length(x) %in% which(x == "t2"):which(x == "t5")))))
#[1] 1 1 1 0 1 1 1 1

编辑

如果您有多个“ t2”和“ t5”,则无需考虑组,因为您仍然要标记它们。 我们可以使用mapply并创建一个索引序列以将flag标记为1。

df$flag <- 0
df$flag[unlist(mapply(":", which(df$time == "t2"), which(df$time == "t5")))] <- 1

和相同的dplyr版本是

df %>%
  mutate(flag = +(row_number() %in% 
          unlist(map2(which(time == "t2"), which(time == "t5"), seq))))

以下是您可以考虑的一种简单方法:

library(dplyr)

df %>%
    mutate(flag = ifelse(time %in% c("t2", "t3", "t4", "t5"), 1, 0))

这将标记您所描述的数据并且可读。

   name  id time flag
1  Anna 100   t2    1
2  Anna 100   t3    1
3  Anna 100   t5    1
4 Jenny 250   t1    0
5 Jenny 250   t2    1
6 Jenny 250   t3    1
7 Jenny 250   t4    1
8 Jenny 250   t5    1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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