如何使用不同的变量来计算新变量,具体取决于哪个变量有缺失值?
How can I use different variables to calculate a new variable, depending on which variable has missing values?
我想创建一个变量 x
,它是变量 e
和其中一个变量 a, b, c
或 d
的乘积。结果变量应取值 a * e
,但如果 a
是 NA
,则它应取值 b * e
,如果缺少 a & b
,则它应该取值 c * e
等等。
例如:如果我的数据框如下所示:
df <- data.frame(a = c(1, 2, NA, NA, 5), b = c(NA, 1, NA, 4, 6), c = c(NA, 3, 3, 3, 7), d = c(1, 1, 1, 1, 1), e = c(1, 2, 3, 4, NA))
我希望得到以下结果:
df$x <- c(1, 4, 9, 16, NA)
我正在尝试通过以下方式实现:
df <- df %>% mutate(x = case_when(!is.na(a) ~ a * e, is.na(a) ~ b * e, is.na(a) & is.na(b) ~ c * e, is.na(a) & is.na(b) & is.na(c) ~ d * e))
不幸的是,这还没有工作,因为 R 不知何故不理解 is.na(a) & is.na(b)
因为两个值同时丢失。
df <-
data.frame(
a = c(1, 2, NA, NA, 5),
b = c(NA, 1, NA, 4, 6),
c = c(NA, 3, 3, 3, 7),
d = c(1, 1, 1, 1, 1),
e = c(1, 2, 3, 4, NA)
)
df$res <- df[, 5] * apply(df[-5], 1, function(x) x[which(x = !is.na(x))[1]])
df
#> a b c d e res
#> 1 1 NA NA 1 1 1
#> 2 2 1 3 1 2 4
#> 3 NA NA 3 1 3 9
#> 4 NA 4 3 1 4 16
#> 5 5 6 7 1 NA NA
由 reprex package (v2.0.1)
于 2022-05-19 创建
这是一个带有 row/column
索引的选项
df$res <- df$e * df[-5][cbind(seq_len(nrow(df)),
max.col(!is.na(df[-5]), 'first'))]
df$res
[1] 1 4 9 16 NA
您可以使用 dplyr
中的 coalesce()
来查找第一个 non-missing 元素。
library(dplyr)
df %>%
mutate(x = e * coalesce(a, b, c, d))
# a b c d e x
# 1 1 NA NA 1 1 1
# 2 2 1 3 1 2 4
# 3 NA NA 3 1 3 9
# 4 NA 4 3 1 4 16
# 5 5 6 7 1 NA NA
如果您有很多列要相乘,您可以使用 across()
中的 tidy-selection 自动执行。 (编辑:感谢 @akrun 的改进)
df %>%
mutate(x = e * do.call(coalesce, across(a:d)))
我想创建一个变量 x
,它是变量 e
和其中一个变量 a, b, c
或 d
的乘积。结果变量应取值 a * e
,但如果 a
是 NA
,则它应取值 b * e
,如果缺少 a & b
,则它应该取值 c * e
等等。
例如:如果我的数据框如下所示:
df <- data.frame(a = c(1, 2, NA, NA, 5), b = c(NA, 1, NA, 4, 6), c = c(NA, 3, 3, 3, 7), d = c(1, 1, 1, 1, 1), e = c(1, 2, 3, 4, NA))
我希望得到以下结果:
df$x <- c(1, 4, 9, 16, NA)
我正在尝试通过以下方式实现:
df <- df %>% mutate(x = case_when(!is.na(a) ~ a * e, is.na(a) ~ b * e, is.na(a) & is.na(b) ~ c * e, is.na(a) & is.na(b) & is.na(c) ~ d * e))
不幸的是,这还没有工作,因为 R 不知何故不理解 is.na(a) & is.na(b)
因为两个值同时丢失。
df <-
data.frame(
a = c(1, 2, NA, NA, 5),
b = c(NA, 1, NA, 4, 6),
c = c(NA, 3, 3, 3, 7),
d = c(1, 1, 1, 1, 1),
e = c(1, 2, 3, 4, NA)
)
df$res <- df[, 5] * apply(df[-5], 1, function(x) x[which(x = !is.na(x))[1]])
df
#> a b c d e res
#> 1 1 NA NA 1 1 1
#> 2 2 1 3 1 2 4
#> 3 NA NA 3 1 3 9
#> 4 NA 4 3 1 4 16
#> 5 5 6 7 1 NA NA
由 reprex package (v2.0.1)
于 2022-05-19 创建这是一个带有 row/column
索引的选项
df$res <- df$e * df[-5][cbind(seq_len(nrow(df)),
max.col(!is.na(df[-5]), 'first'))]
df$res
[1] 1 4 9 16 NA
您可以使用 dplyr
中的 coalesce()
来查找第一个 non-missing 元素。
library(dplyr)
df %>%
mutate(x = e * coalesce(a, b, c, d))
# a b c d e x
# 1 1 NA NA 1 1 1
# 2 2 1 3 1 2 4
# 3 NA NA 3 1 3 9
# 4 NA 4 3 1 4 16
# 5 5 6 7 1 NA NA
如果您有很多列要相乘,您可以使用 across()
中的 tidy-selection 自动执行。 (编辑:感谢 @akrun 的改进)
df %>%
mutate(x = e * do.call(coalesce, across(a:d)))