如何评估 R 中 data.frame 组中先前值满足的条件

How to evaluate conditions met on previous values within a group in a data.frame in R

在此先感谢您对这个问题的帮助,SQ 可爱的人们,我有一个如下所示的数据集:

library(tidyverse)   
 name<-c("AAA","AAA","AAA")
    value<-c(1:3)
    order<-c(2,3,6)
    tag<-c(0,0,0)
    part_a<-data.frame(name,value,order,tag)
    name<-c("AAA","AAA","AAA")
    value<-c(1:3)
    order<-c(1,5,4)
    key<-c(1,1,1)
    part_b<-data.frame(name,value,order,key)
    df<-bind_rows(part_a,part_b)
    df %>% group_by(name) %>% arrange(order)


    Groups:   name [1]
      name  value order   tag   key
      <chr> <int> <dbl> <dbl> <dbl>
    1 AAA       1     1    NA     1
    2 AAA       1     2     0    NA
    3 AAA       2     3     0    NA
    4 AAA       3     4    NA     1
    5 AAA       2     5    NA     1
    6 AAA       3     6     0    NA

我正在尝试编写一个代码,允许我创建两个名为 CHECK_1CHECK_2 的新变量,CHECK_1 需要有两个值,如果列 tag 的前一个值是 NA 并且列 key 的前一个值不是 NA 和 0 否则,变量 CHECK_2 只需要有两个值,它应该是“out of如果列 order 的当前值和先前值之间的差异大于 3,则为“范围”,否则为“在范围内”。 此操作必须在数据框中的组内完成,我知道我可以使用基本 R 函数 lag() 但我尝试将条件合并到 if_else 语句中但没有成功,谢谢这么多你的帮助伙计们!发自内心

我想要的输出是:

name value order tag key check_1 check_2
AAA 1 1 NA 1 1 "within range"
AAA 1 2 0 NA 0 "within range"
AAA 2 3 0 NA 0 "within range"
AAA 3 4 NA 1 1 "within range"
AAA 2 5 NA 1 1 "within range"
AAA 3 6 0 NA 0 "within range"

你可以用 tidyverse 做这样的事情。但是,我不确定您想对组的第一行值做什么。

library(tidyverse)

df %>% 
  group_by(name) %>% 
  arrange(order) %>% 
  mutate(check_1 = ifelse(is.na(lag(tag)) & !is.na(lag(key)), 1, 0),
         check_2 = ifelse(order - lag(order) > 3, "out of range", "within range"))

输出

  name  value order   tag   key check_1 check_2     
  <chr> <int> <dbl> <dbl> <dbl>   <dbl> <chr>       
1 AAA       1     1    NA     1       0 NA          
2 AAA       1     2     0    NA       1 within range
3 AAA       2     3     0    NA       0 within range
4 AAA       3     4    NA     1       0 within range
5 AAA       2     5    NA     1       1 within range
6 AAA       3     6     0    NA       1 within range

如果您想将第一行的值默认为 1 和“在范围内”,那么我们可以使用 case_when 来创建一个额外的 ifelse 条件。

df %>% 
  group_by(name) %>% 
  arrange(order) %>% 
  mutate(check_1 = case_when(row_number() == 1 ~ 1,
                             is.na(lag(tag)) & !is.na(lag(key)) ~ 1, 
                             TRUE ~ 0),
         check_2 = case_when(row_number() == 1 ~ "within range",
                             order - lag(order) > 3 ~ "out of range", 
                             TRUE ~ "within range"))

  name  value order   tag   key check_1 check_2     
  <chr> <int> <dbl> <dbl> <dbl>   <dbl> <chr>       
1 AAA       1     1    NA     1       1 within range
2 AAA       1     2     0    NA       1 within range
3 AAA       2     3     0    NA       0 within range
4 AAA       3     4    NA     1       0 within range
5 AAA       2     5    NA     1       1 within range
6 AAA       3     6     0    NA       1 within range