根据组内的先前值创建新的计数变量
Create new count variable conditional on previous values within group
我有一个包含组和时间 ID 的数据框。现在我想创建一个新的计数变量,称为 X2
,以每个组中 X1
的先前值为条件。
假设我有以下数据框、变量 group
、time
、X1
,并且想要创建 X2
。 X2
的值应该是一个计数变量,指示自 X1
最后一次在给定组中等于 1 以来的周期数(即行数)。如果 X1
的所有先前值均为 0,则 X2
应该缺失。
group time X1 X2
1 1 1 0 NA
2 1 2 0 NA
3 1 3 1 NA
4 1 4 0 0
5 1 5 1 1
6 2 1 0 NA
7 2 2 1 NA
8 2 3 1 0
9 2 4 1 0
10 2 5 0 0
11 3 1 0 NA
12 3 2 0 NA
13 3 3 0 NA
14 3 4 1 NA
15 3 5 0 0
16 4 1 1 NA
17 4 2 0 0
18 4 3 0 1
19 4 4 0 2
20 4 5 1 3
data_test <- data.frame(
group = rep(1:4, each = 5),
time = rep(1:5, n = 4),
X1 = c(0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1),
X2 = c(NA, NA, NA, 0, 1, NA, NA, 0, 0, 0, NA, NA, NA, NA, 0, NA, 0, 1, 2, 3))
我可以通过使用带 cumsum()==0
的 if 命令轻松创建 NA。但是,我不知道如何处理另一部分,即创建计数。
任何帮助将不胜感激 - 如果可能的话使用 dplyr
。
非常感谢。
使用 dplyr
包
中的管道 (%>%
)、mutate
、group_by
和 lag
函数
library(dplyr)
data_test %>%
group_by(group) %>%
mutate(X2 = ifelse(lag(X1) == 1, 0, lag(X2) + 1))
这确实假设 time
中的差异始终为 1,如示例数据所示。如果 time
在您的数据中有所不同,并且 X2
应该反映 time
中的差异:
data_test %>%
group_by(group) %>%
mutate(X2 = ifelse(lag(X1) == 1, 0, lag(X2) + (time - lag(time))))
这不是很优雅,但它包含了我认为提供的规则。
为 X1
为 1 的行号添加一列,并使用 fill
,以便您可以使用适用于该条件的最新行号。
要计算X2_new
,如果X1
为0,则为组内当前行号减去X1
为1的最后行号之间的差值。如果X1
是 1(而不是组中 1 的第一个 X1
),然后做类似的计算,但在前面的 rn
参考上。
library(tidyverse)
data_test %>%
group_by(group) %>%
mutate(rn = ifelse(X1 == 1, row_number(), NA)) %>%
fill(rn) %>%
mutate(X2_new = ifelse(X1 == 0 & row_number() > rn, row_number() - rn - 1, NA),
X2_new = ifelse(X1 == 1 & !is.na(lag(rn)), row_number() - lag(rn) - 1, X2_new)) %>%
select(-rn)
输出
# A tibble: 20 x 5
# Groups: group [4]
group time X1 X2 X2_new
<int> <int> <dbl> <dbl> <dbl>
1 1 1 0 NA NA
2 1 2 0 NA NA
3 1 3 1 NA NA
4 1 4 0 0 0
5 1 5 1 1 1
6 2 1 0 NA NA
7 2 2 1 NA NA
8 2 3 1 0 0
9 2 4 1 0 0
10 2 5 0 0 0
11 3 1 0 NA NA
12 3 2 0 NA NA
13 3 3 0 NA NA
14 3 4 1 NA NA
15 3 5 0 0 0
16 4 1 1 NA NA
17 4 2 0 0 0
18 4 3 0 1 1
19 4 4 0 2 2
20 4 5 1 3 3
我有一个包含组和时间 ID 的数据框。现在我想创建一个新的计数变量,称为 X2
,以每个组中 X1
的先前值为条件。
假设我有以下数据框、变量 group
、time
、X1
,并且想要创建 X2
。 X2
的值应该是一个计数变量,指示自 X1
最后一次在给定组中等于 1 以来的周期数(即行数)。如果 X1
的所有先前值均为 0,则 X2
应该缺失。
group time X1 X2
1 1 1 0 NA
2 1 2 0 NA
3 1 3 1 NA
4 1 4 0 0
5 1 5 1 1
6 2 1 0 NA
7 2 2 1 NA
8 2 3 1 0
9 2 4 1 0
10 2 5 0 0
11 3 1 0 NA
12 3 2 0 NA
13 3 3 0 NA
14 3 4 1 NA
15 3 5 0 0
16 4 1 1 NA
17 4 2 0 0
18 4 3 0 1
19 4 4 0 2
20 4 5 1 3
data_test <- data.frame(
group = rep(1:4, each = 5),
time = rep(1:5, n = 4),
X1 = c(0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1),
X2 = c(NA, NA, NA, 0, 1, NA, NA, 0, 0, 0, NA, NA, NA, NA, 0, NA, 0, 1, 2, 3))
我可以通过使用带 cumsum()==0
的 if 命令轻松创建 NA。但是,我不知道如何处理另一部分,即创建计数。
任何帮助将不胜感激 - 如果可能的话使用 dplyr
。
非常感谢。
使用 dplyr
包
%>%
)、mutate
、group_by
和 lag
函数
library(dplyr)
data_test %>%
group_by(group) %>%
mutate(X2 = ifelse(lag(X1) == 1, 0, lag(X2) + 1))
这确实假设 time
中的差异始终为 1,如示例数据所示。如果 time
在您的数据中有所不同,并且 X2
应该反映 time
中的差异:
data_test %>%
group_by(group) %>%
mutate(X2 = ifelse(lag(X1) == 1, 0, lag(X2) + (time - lag(time))))
这不是很优雅,但它包含了我认为提供的规则。
为 X1
为 1 的行号添加一列,并使用 fill
,以便您可以使用适用于该条件的最新行号。
要计算X2_new
,如果X1
为0,则为组内当前行号减去X1
为1的最后行号之间的差值。如果X1
是 1(而不是组中 1 的第一个 X1
),然后做类似的计算,但在前面的 rn
参考上。
library(tidyverse)
data_test %>%
group_by(group) %>%
mutate(rn = ifelse(X1 == 1, row_number(), NA)) %>%
fill(rn) %>%
mutate(X2_new = ifelse(X1 == 0 & row_number() > rn, row_number() - rn - 1, NA),
X2_new = ifelse(X1 == 1 & !is.na(lag(rn)), row_number() - lag(rn) - 1, X2_new)) %>%
select(-rn)
输出
# A tibble: 20 x 5
# Groups: group [4]
group time X1 X2 X2_new
<int> <int> <dbl> <dbl> <dbl>
1 1 1 0 NA NA
2 1 2 0 NA NA
3 1 3 1 NA NA
4 1 4 0 0 0
5 1 5 1 1 1
6 2 1 0 NA NA
7 2 2 1 NA NA
8 2 3 1 0 0
9 2 4 1 0 0
10 2 5 0 0 0
11 3 1 0 NA NA
12 3 2 0 NA NA
13 3 3 0 NA NA
14 3 4 1 NA NA
15 3 5 0 0 0
16 4 1 1 NA NA
17 4 2 0 0 0
18 4 3 0 1 1
19 4 4 0 2 2
20 4 5 1 3 3