在R中,返回数据框每行缺失(NA)数据的列名称列表

4

我正在尝试创建一个数据列表,其中包含数据框中每个ID#的NA值,以便我可以跟踪缺失的数据。我的数据框中,每行都是一个ID#,每列都是一个变量名。每个ID#可能具有不同的缺失数据,因此我希望将这些信息压缩成一个两列表格。目前,我的表格看起来像这样:

ID  Var1 Var2 Var3 Var4 Var5
1   10   T    NA   2    NA
2   15   F    50   2    NA
3   12   NA   41   2    NA
4   NA   NA   NA   1    NA
5   NA   F    NA   NA   NA
...

我希望能得到类似于以下输出:

ID   Missing Variables
1    Var3, Var5
2    Var5
3    Var2, Var5
4    Var1, Var2, Var3, Var5
5    Var1, Var3, Var4, Var5
...

我感到困惑,如何为每个丢失的数据条目返回列名。我知道你可以用for循环做一些事情,但除此之外,我会有点迷失。非常感谢任何帮助!


which.na()可能会有帮助,尽管我不太确定具体如何使用。 - AnilGoyal
相关: 对于每一行,获取数据等于某个值的列名; ix = which(is.na(df), arr.ind = TRUE); tapply(names(df)[ix[ , 2]], ix[, 1], toString) - Henrik
4个回答

7

这里提供了一个tidyverse的解决方案。

df <- read_table("
ID  Var1 Var2 Var3 Var4 Var5
1   10   T    NA   2    NA
2   15   F    50   2    NA
3   12   NA   41   2    NA
4   NA   NA   NA   1    NA
5   NA   F    NA   NA   NA", col_names = TRUE)

library(dplyr)
library(tidyr)
df %>%
  mutate(across(starts_with("var"), is.na)) %>%  # replace all NA with TRUE and else FALSE
  pivot_longer(-ID, names_to = "var") %>%  # pivot longer
  filter(value) %>%   # remove the FALSE rows
  group_by(ID) %>%    # group by the ID
  summarise(`Missing Variables` = toString(var)) # convert the variable names to a string column

`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 5 x 2
     ID `Missing Variables`   
  <dbl> <chr>                 
1     1 Var3, Var5            
2     2 Var5                  
3     3 Var2, Var5            
4     4 Var1, Var2, Var3, Var5
5     5 Var1, Var3, Var4, Var5

牛逼的解决方案。我一直想知道tidyverse关于覆盖参数的警告信息是什么意思?有没有办法避免这个警告? - AnilGoyal
1
@AnilGoyal - 默认情况下,summarize 现在不再对数据进行分组。这在 dplyr v. 1.0 之前是不同的。警告是为了帮助用户理解 summarize 的行为发生了变化。 - Ben Norris
抱歉,Ben已经帮你解答了!你也可以使用stringr中的str_c函数,对吧?summarize("缺失变量" = str_c(Missing_Variables, collapse = ", ")) - Eric
1
@iamericfletcher - toString(x)基本上是paste0(x, collapse = ", ")的简写形式,而这正是str_c所复制的。 - Ben Norris
1
嗨 @AnilGoyal,你所寻找的是:options(dplyr.summarise.inform = FALSE) - Matteo Castagna
显示剩余4条评论

3

以下是可能的基于R语言的方法,返回一个向量:

result <- apply(
  X = is.na(my_df),
  MARGIN = 1,
  FUN = function(x) paste(colnames(my_df)[x], collapse = ", ")
)

> result
[1] "Var3, Var5"             "Var5"                   "Var2, Var5"             "Var1, Var2, Var3, Var5" "Var1, Var3, Var4, Var5"

看起来你正在请求一个data.frame对象,你可以很容易地得到它:

data.frame(ID = my_df$ID, `Missing Variables` = result, check.names = FALSE)

# Note that the data.frame specification does not consider variable names
# containing spaces to be syntactically valid, so you have to disable the
# check if you want the variable name you have specified. This may cause
# other problems 'down the line'.

  ID      Missing Variables
1  1             Var3, Var5
2  2                   Var5
3  3             Var2, Var5
4  4 Var1, Var2, Var3, Var5
5  5 Var1, Var3, Var4, Var5

不过,你也说了你正在寻找一个列表 - 如果是这样的话:

> setNames(as.list(result), test$ID)

$`1`
[1] "Var3, Var5"

$`2`
[1] "Var5"

$`3`
[1] "Var2, Var5"

$`4`
[1] "Var1, Var2, Var3, Var5"

$`5`
[1] "Var1, Var3, Var4, Var5"

0

dplyr 的方式解决它

df <- read.table(text = 'ID  Var1 Var2 Var3 Var4 Var5
1   10   T    NA   2    NA
2   15   F    50   2    NA
3   12   NA   41   2    NA
4   NA   NA   NA   1    NA
5   NA   F    NA   NA   NA', header = T)
library(dplyr)

df %>%
  rowwise() %>%
  summarise(ID, missing = toString(names(.)[-1][seq_along(c_across(starts_with('Var'))) * is.na(c_across(starts_with('Var')))]),
            .groups = 'drop')

#> # A tibble: 5 x 2
#>      ID missing               
#>   <int> <chr>                 
#> 1     1 Var3, Var5            
#> 2     2 Var5                  
#> 3     3 Var2, Var5            
#> 4     4 Var1, Var2, Var3, Var5
#> 5     5 Var1, Var3, Var4, Var5

本内容由reprex包(v2.0.0)于2021年5月15日创建


0
这个工作吗?
> library(dplyr)
> df
# A tibble: 5 x 6
     ID  Var1 Var2   Var3  Var4 Var5 
  <dbl> <dbl> <lgl> <dbl> <dbl> <lgl>
1     1    10 TRUE     NA     2 NA   
2     2    15 FALSE    50     2 NA   
3     3    12 NA       41     2 NA   
4     4    NA NA       NA     1 NA   
5     5    NA FALSE    NA    NA NA   
> df$reps <- sapply(apply(df[2:6], 1, function(x) which(is.na(x))), names)
> df %>% unnest(reps) %>% group_by(ID) %>% summarise(`Missing Variables` = paste0(reps, collapse = ', '))
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 5 x 2
     ID `Missing Variables`   
  <dbl> <chr>                 
1     1 Var3, Var5            
2     2 Var5                  
3     3 Var2, Var5            
4     4 Var1, Var2, Var3, Var5
5     5 Var1, Var3, Var4, Var5

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