将变量的名称分配给具有多个变量的数据框中的非 NA

Assign the name of the variable to a non NA in a data frame with multiple variables

比如我的df是:

         >dfABy 
         A    B     C

         56   NA  NA
         NA   45  NA
         NA   77  NA 
         67   NA  12 
         NA   65  3

我要实现如下数据框

         >dfABy 
         A    B    C

         A    NA  NA
         NA   B   NA
         NA   B   NA 
         A    NA  C
         NA   B   C

这是base R中的一个选项。将数据转换为逻辑矩阵,非 NA 为 TRUE,NA 为 FALSE。根据 colum 索引 ('nm1') 复制列名。根据索引'i1'将数据中的元素赋值给对应的列名

i1 <- !is.na(dfABy)
nm1 <- names(dfABy)[col(dfABy)]
dfABy[i1] <- nm1[i1]

-输出

dfABy
#     A    B    C
#1    A <NA> <NA>
#2 <NA>    B <NA>
#3 <NA>    B <NA>
#4    A <NA>    C
#5 <NA>    B    C

或单行

dfABy[] <- names(dfABy)[col(dfABy)][(NA^is.na(dfABy)) * col(dfABy)]

或使用tidyverse

library(dplyr)
dfABy %>%
    mutate(across(everything(), ~ replace(., !is.na(.), cur_column())))
#     A    B    C
#1    A <NA> <NA>
#2 <NA>    B <NA>
#3 <NA>    B <NA>
#4    A <NA>    C
#5 <NA>    B    C

数据

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

另一种选择是使用 purrr 包:

library(purrr)
 
df <- data.frame(A = c(56, NA, NA, 67, NA), B = c(NA, 45, 77, NA, 65), C = c(NA, NA, NA,12, 3))
 
imap_dfc(df, ~ifelse(is.na(.x), NA, .y))
# A tibble: 5 x 3
  A     B     C    
  <chr> <chr> <chr>
1 A     NA    NA   
2 NA    B     NA   
3 NA    B     NA   
4 A     NA    C    
5 NA    B     C   

Map 的基本 R 选项:

dfABy[] <- Map(function(x, y) ifelse(is.na(x), NA, y), dfABy, names(dfABy))
dfABy

#     A    B    C
#1    A <NA> <NA>
#2 <NA>    B <NA>
#3 <NA>    B <NA>
#4    A <NA>    C
#5 <NA>    B    C