我是dplyr的新手,曾尝试使用dplyr和ifelse
从三个不同的年龄变量创建一个新的复合变量。我制作了一个数据框架来解释如下情况:
library(dplyr)
z <- data.frame("j6" = c(6, 19, NA, NA, NA, NA, NA, 8, 20, 20, NA),
"j7" = c(27, 20, NA, 7, 19, NA, NA, 20, 30, 9, NA),
"j8" = c(8, 22, NA, 20, NA, 8, 30, NA, NA, NA, 3))
z <- z %>%
mutate(., age_event = NA) %>%
mutate(., age_event = ifelse(j6 < 18 | j7 < 18 | j8 < 18, 1, 0))
我的期望:
- 三列(j6、j7和j8(表示年龄,如果其中至少有一列年龄小于18岁,则新列(age_event(应为"1",否则为0
- 如果三列中的两列都是18岁或以上,而另一列是NA,则age_event变量应为0
- 同样,如果三列中的一列为18岁或18岁以上,而其他列为NA,则age_event变量应为0
- 如果这三列都是NA,那么它也是NA
然而,结果和问题如下所示:
> z
j6 j7 j8 age_event
1 6 27 8 1
2 19 20 22 0
3 NA NA NA NA
4 NA 7 20 1
5 NA 19 NA NA <-- should be 0, but NA
6 NA NA 8 1
7 NA NA 30 NA <-- should be 0, but NA
8 8 20 NA 1
9 20 30 NA NA <-- should be 0, but NA
10 20 9 NA 1
11 NA NA 3 1
我想知道是否有办法使用mutate
和ifelse
将上面的第5、第7和第9个观测值转换为0。如有任何建议,我们将不胜感激!
更新(2020年2月27日(:当使用mutate
和ifelse
:时,我发现了pmin
的解决方案
z <- z %>%
mutate(., age_event = ifelse(is.na(j6) & is.na(j7) & is.na(j8), NA,
ifelse(pmin(j6, j7, j8, na.rm = T) < 18, 1, 0)))
> z
j6 j7 j8 age_event
1 6 27 8 1
2 19 20 22 0
3 NA NA NA NA
4 NA 7 20 1
5 NA 19 NA 0
6 NA NA 8 1
7 NA NA 30 0
8 8 20 NA 1
9 20 30 NA 0
10 20 9 NA 1
11 NA NA 3 1
您可以使用rowMeans()
来代替if_else()
,后者将处理全部为NA
的情况。
z %>%
mutate(age_event = +(rowMeans(. < 18, na.rm = TRUE) > 0))
j6 j7 j8 age_event
1 6 27 8 1
2 19 20 22 0
3 NA NA NA NA
4 NA 7 20 1
5 NA 19 NA 0
6 NA NA 8 1
7 NA NA 30 0
8 8 20 NA 1
9 20 30 NA 0
10 20 9 NA 1
11 NA NA 3 1
我们可以使用rowSums
来计算一行中NA
值的数量和小于18的值的数量。然后,我们可以使用case_when
根据不同的条件进行编号。
library(dplyr)
z %>%
mutate(calc = rowSums(!is.na(.), na.rm = TRUE),
ls18 = rowSums(. < 18, na.rm = TRUE),
age_event = case_when(calc == 0 & ls18 == 0 ~ NA_integer_,
ls18 > 0 ~ 1L,
TRUE ~ 0L)) %>%
select(-calc, -ls18)
# j6 j7 j8 age_event
#1 6 27 8 1
#2 19 20 22 0
#3 NA NA NA NA
#4 NA 7 20 1
#5 NA 19 NA 0
#6 NA NA 8 1
#7 NA NA 30 0
#8 8 20 NA 1
#9 20 30 NA 0
#10 20 9 NA 1
#11 NA NA 3 1