如何评估 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_1
和 CHECK_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
在此先感谢您对这个问题的帮助,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_1
和 CHECK_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