将数据框中的列与部分信息组合在一起

Combining columns in a dataframe each with partial information

我有一个大数据集,它在不同时间段对相同变量使用不同的编码方案。每个时间段的编码表示为一列,其中包含它活跃的那一年的值,而其他地方则为 NA。

我能够 "combine" 通过使用嵌套的 ifelse 命令和 dplyr 的 mutate [见下面的编辑] 来 "combine" 它们,但是我 运行 遇到了使用 ifelse 做一些稍微不同的事情的问题。我想根据之前的任何变量是否满足条件来编写一个新变量。但由于某种原因,下面的 ifelse 结构不起作用。

MWE:

library("dplyr")
library("magrittr")
df <- data.frame(id = 1:12, year = c(rep(1995, 5), rep(1996, 5), rep(1997, 2)), varA = c("A","C","A","C","B",rep(NA,7)), varB = c(rep(NA,5),"B","A","C","A","B",rep(NA,2)))
df %>% mutate(varC = ifelse(varA == "C" | varB == "C", "C", "D"))

输出:

> df
   id year varA varB varC
1   1 1995    A <NA> <NA>
2   2 1995    C <NA>    C
3   3 1995    A <NA> <NA>
4   4 1995    C <NA>    C
5   5 1995    B <NA> <NA>
6   6 1996 <NA>    B <NA>
7   7 1996 <NA>    A <NA>
8   8 1996 <NA>    C    C
9   9 1996 <NA>    A <NA>
10 10 1996 <NA>    B <NA>
11 11 1997 <NA> <NA> <NA>
12 12 1997 <NA> <NA> <NA>

如果我不使用 | 运算符,并且仅针对 varA 进行测试,它会得出预期的结果,但它仅适用于 varA 不为 NA 的年份。

输出:

> df %<>% mutate(varC = ifelse(varA == "C", "C", "D"))
> df
   id year varA varB varC
1   1 1995    A <NA>    D
2   2 1995    C <NA>    C
3   3 1995    A <NA>    D
4   4 1995    C <NA>    C
5   5 1995    B <NA>    D
6   6 1996 <NA>    B <NA>
7   7 1996 <NA>    A <NA>
8   8 1996 <NA>    C <NA>
9   9 1996 <NA>    A <NA>
10 10 1996 <NA>    B <NA>
11 11 1997 <NA> <NA> <NA>
12 12 1997 <NA> <NA> <NA>

期望的输出:

> df
   id year varA varB varC
1   1 1995    A <NA>    D
2   2 1995    C <NA>    C
3   3 1995    A <NA>    D
4   4 1995    C <NA>    C
5   5 1995    B <NA>    D
6   6 1996 <NA>    B    D
7   7 1996 <NA>    A    D
8   8 1996 <NA>    C    C
9   9 1996 <NA>    A    D
10 10 1996 <NA>    B    D
11 11 1997 <NA> <NA> <NA>
12 12 1997 <NA> <NA> <NA>

我怎样才能得到我要找的东西?

为了让这个问题更适用于更广泛的受众,并从这种情况中吸取教训,最好能解释一下使用 | 进行比较导致它不起作用的原因正如预期的那样。提前致谢!

编辑:这就是我将它们与嵌套 ifelses 成功组合的意思

> df %>% mutate(varC = ifelse(year == 1995, as.character(varA), 
+                             ifelse(year == 1996, as.character(varB), NA)))
   id year varA varB varC
1   1 1995    A <NA>    A
2   2 1995    C <NA>    C
3   3 1995    A <NA>    A
4   4 1995    C <NA>    C
5   5 1995    B <NA>    B
6   6 1996 <NA>    B    B
7   7 1996 <NA>    A    A
8   8 1996 <NA>    C    C
9   9 1996 <NA>    A    A
10 10 1996 <NA>    B    B
11 11 1997 <NA> <NA> <NA>
12 12 1997 <NA> <NA> <NA>

根据@Khashaa 评论。这应该可以解决问题并让您获得所需的输出。

df %>%
  mutate(varC = ifelse(is.na(varA) & is.na(varB), NA, 
                       ifelse(varA %in% "C" | varB %in% "C", "C", "D")))

R 有这种烦人的倾向,其中涉及 NA 的条件的逻辑值只是 NA,而不是 true 或 false。 即 NA>0 = NA 而不是 FALSE

NA 与 TRUE 的交互就像 false 一样。即 TRUE|NA = TRUE。 TRUE&NA = NA.

有趣的是,它还与 FALSE 交互,就好像它是 TRUE 一样。即 FALSE|NA=NA。假&NA=假

其实NA就像一个介于TRUE和FALSE之间的逻辑值。例如不适用|真|假 = 真。

所以这里有一个破解方法:

ifelse((varA=='C'&!is.na(varA))|(varB=='C'&!is.na(varB))

我们如何解释这一点?在 OR 的左侧,我们有以下内容:如果 varA 为 NA,则我们有 NA&FALSE。由于 NA 在逻辑层次结构中比 FALSE 高一级,& 将强制整个事物为 FALSE。否则,如果 varA 不是 NA 但不是 'C',您将得到 FALSE&TRUE,它会根据需要给出 FALSE。否则,如果它是 'C',它们都为真。 OR右边的东西也是一样。

当使用涉及x但x可以为NA的条件时,我喜欢使用 ((condition for x)&!is.na(x)) 完全排除 NA 输出并在我想要的情况下强制使用 TRUE 或 FALSE 值。

编辑:我只记得如果它们都是 NA,您需要 NA 输出。这并没有结束,所以这是我的错。除非当它们都是 NA 时你对 'D' 输出没意见。

EDIT2:这应该根据需要输出 NA:

ifelse(is.na(varA)&is.na(varB), NA, ifelse((varA=='C'&!is.na(varA))|(varB=='C'&!is.na(varB)), 'C','D'))