在数据框中使用现有变量名称创建一个新变量,在每个变量列表中匹配非 NA 值时填充它

Create a new variable with an existing variable name in a data frame, filling it when matching a non NA value in each of the variable lists

我想在 dfABy 中使用现有变量的名称创建一个列 - C - 当在列表 A 或 B 中时它是一个“非 NA”值。比如我的df是:

             >dfABy 
             A    B 
             56   NA  
             NA   45  
             NA   77  
             67   NA  
             NA   65  

我参加的结果是:

             > dfABy
             A    B   C
             56   NA  A
             NA   45  B
             NA   77  B
             67   NA  A
             NA   65  B

您可以使用 max.col 而不是 is.na 值来获取存在非 NA 值的列号。从这些数字中,您可以获得列名。

dfABy$C <- names(dfABy)[max.col(!is.na(dfABy))] 
dfABy

#   A  B C
#1 56 NA A
#2 NA 45 B
#3 NA 77 B
#4 67 NA A
#5 NA 65 B

如果一行中有多个非 NA 值,请查看 ?max.col 中的 ties.method 参数,了解如何处理平局。

数据

dfABy <- structure(list(A = c(56L, NA, NA, 67L, NA), B = c(NA, 45L, 77L, 
NA, 65L)), class = "data.frame", row.names = c(NA, -5L))

使用 dplyr 的一个选项可能是:

df %>%
    rowwise() %>%
    mutate(C = names(.[!is.na(c_across(everything()))]))

      A     B C    
  <int> <int> <chr>
1    56    NA A    
2    NA    45 B    
3    NA    77 B    
4    67    NA A    
5    NA    65 B

或加上purrr:

df %>%
    mutate(C = pmap_chr(across(A:B), ~ names(c(...)[!is.na(c(...))])))

使用我推荐的data.table包:

dfABy[, C := apply(cbind(dfABy), 1, function(x) names(x[!is.na(x)]))]

创建以下输出:

    A   B   C
1   56  NA  A
2   NA  45  B
3   NA  77  B
4   67  NA  A
5   NA  65  B

这只是另一种解决方案,但是其他建议的解决方案更好。

library(dplyr)
library(purrr)

df %>%
  rowwise() %>%
  mutate(C = detect_index(c(A, B), ~ !is.na(.x)), 
         C = names(.[C]))

# A tibble: 5 x 3
# Rowwise: 
      A     B C    
  <dbl> <dbl> <chr>
1    56    NA A    
2    NA    45 B    
3    NA    77 B    
4    67    NA A    
5    NA    65 B