按变量分组,然后查找 R 中每列缺失值的比例

Grouping by a variable, then finding proportion of missing values for each column in R

我有一个带有因子变量的数据框和带有几个 NA 的列,如图所示。

var col1 col2 col3
C    1    NA   1
A    NA   1    1 
C    NA   NA   NA
A    1    NA   1
B    NA   1    1
A    1    1    1
B    1    NA   1
B    1    1    1
C    NA   NA   1
B    NA   1   1

我正在寻找一种方法来对变量进行分组并获取每列缺失值的比例,按 'var' 中的水平分组。输出应如下所示:

var col1 col2 col3
A    0.33 0.33  0
B    0.5  0.25  0 
C    0.66 1.00  0.33

任何方法都可以,我们将不胜感激,但最好使用简单的 dplyr 方法。谢谢!

编辑: 我正在寻找一种方法,允许我一次对多个列执行此操作,return 一个类似于我的数据框如上所示。

假设我的数据被命名为 'df' 那么,我想一次获得所有列的缺失比例 而不必再次手动输入名称。

以下代码不起作用,但它是我想要实现的目标的总体思路。也许一个功能可以提供帮助,但我不确定我将如何处理它。

df %>% group_by(var) %>% summarise(names(df[,-1]) = sum(is.na(names(df[,-1])))/n())

您可以尝试这样的操作:

# Create some arbitrary matrix
rs <- 100
dat <- data.frame(matrix(1,rs,3))

for(i in 1:rs){
dat[i,sample(1:3,2,)] <- NA
}

dat <- cbind(rep(c("A","B","C"),rs)[1:rs],dat)

colnames(dat)[1] <- "var"

# Use the by function with an apply statement
by(dat[,c("X1","X2","X3")],dat[,"var"],function(x) apply(x,2,function(z){
    n <- length(z)
    miss <- sum(is.na(z))
    prop <- miss/n
    }))

假设您的数据在数据框中 data,您可以执行以下操作:

## Your data:
data <- structure(list(var = structure(c(3L, 1L, 3L, 1L, 
    2L, 1L, 2L, 2L, 3L, 2L), .Label = c("A", "B", "C"), 
    class = "factor"), col1 = c(1, NA, NA, 1, NA, 1, 1, 1, NA, NA), 
    col2 = c(NA, 1, NA, NA, 1, 1, NA, 1, NA, 1), 
    col3 = c(1, 1, NA, 1, 1, 1, 1, 1, 1, 1)), 
    .Names = c("var", "col1", "col2", "col3"), 
    row.names = c(NA, -10L), class = "data.frame")

library(dplyr)
outDf <- data %>% group_by(var) %>%
    dplyr::summarise(col1 = sum(is.na(col1))/n(),
                  col2 = sum(is.na(col2))/n(),
                  col3 = sum(is.na(col3))/n())

outDf 
### A tibble: 3 × 4
##     var      col1      col2      col3
##  <fctr>     <dbl>     <dbl>     <dbl>
##1      A 0.3333333 0.3333333 0.0000000
##2      B 0.5000000 0.2500000 0.0000000
##3      C 0.6666667 1.0000000 0.3333333

编辑: 要一次调用将其应用于所有列,您可以使用:

outDf <- data %>% group_by(var) %>%
  dplyr::summarise_all(function(x) sum(is.na(x))/length(x))

outDf
### A tibble: 3 × 4
##     var      col1      col2      col3
##  <fctr>     <dbl>     <dbl>     <dbl>
##1      A 0.3333333 0.3333333 0.0000000
##2      B 0.5000000 0.2500000 0.0000000
##3      C 0.6666667 1.0000000 0.3333333

这是一个更通用的 dplyr 解决方案 summarise_each,它将接受任意数量的列:

df1 <-read.table(text="var col1 col2 col3
C    1    NA   1
A    NA   1    1
C    NA   NA   NA
A    1    NA   1
B    NA   1    1
A    1    1    1
B    1    NA   1
B    1    1    1
C    NA   NA   1
B    NA   1   1",header=TRUE, stringsAsFactors=FALSE)

library(dplyr)
df1 %>%
group_by(var) %>%
summarise_each(funs(sum(is.na(.))/length(.)))

# A tibble: 3 × 4
    var      col1      col2      col3
  <chr>     <dbl>     <dbl>     <dbl>
1     A 0.3333333 0.3333333 0.0000000
2     B 0.5000000 0.2500000 0.0000000
3     C 0.6666667 1.0000000 0.3333333

我们也可以用 aggregate 来自 base R

aggregate(.~var, data, FUN = function(x) sum(is.na(x))/length(x), na.action=NULL)
#  var      col1      col2      col3
#1   A 0.3333333 0.3333333 0.0000000
#2   B 0.5000000 0.2500000 0.0000000
#3   C 0.6666667 1.0000000 0.3333333

data.table

library(data.table)
setDT(data)[, lapply(.SD, function(x) sum(is.na(x))/.N), var]