如果有变量缺失值,我该如何使用不同的变量计算一个新的变量?

4
我希望创建一个变量x,该变量是变量e和变量a、b、cd中的其中一个的乘积。所得变量应该取值a * e,但如果aNA,则应该取值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) 表示两个值同时缺失的意思。

你的数据框有误,长度不同。 - Onyambu
x的第三个值不应该是3 * 3 = 9吗? - dcarlson
@dcarlos,同样正确,谢谢您的评论! - Anton
将来参考:当我使用is.na(a) & is.na(b)时会发生什么?为什么它不能像a>1 & b>2那样工作? - Anton
3个回答

2

这里有一个使用 行/列 索引的选项

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

2
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

本文创建于2022-05-19,使用reprex 包 (v2.0.1)。


谢谢您的建议!有没有可能以只使用变量名的方式表述呢?我的实际数据集包含许多变量,我希望编写一种允许我按名称调用列并执行代码的方法,而不考虑列的位置。谢谢! - Anton
在@Yuriy Saraykin的基础上稍作变化:apply(df, 1, function(x) head(na.omit(x[c("a", "b", "c", "d", "e")]), 1) * x["e"]) - dcarlson

2

您可以使用dplyr中的coalesce()函数来查找第一个非缺失元素。

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()中的整洁选择来自动化它。(编辑:感谢@akrun的改进)

df %>%
  mutate(x = e * do.call(coalesce, across(a:d)))

在这种方法的基础上,我如何创建一个变量来告诉我,前一次计算中使用了哪个变量? - Anton
@Anton 类似这样:df %>% mutate(x = do.call(coalesce, across(a:d, ~ replace(.x, !is.na(.x), cur_column())))) - Darren Tsai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接