按变量分组,然后查找R

时间:2017-04-15 21:45:19

标签: r dplyr tidyverse

我有一个带有因子变量的数据帧和带有几个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 col1 col2 col3
A    0.33 0.33  0
B    0.5  0.25  0 
C    0.66 1.00  0.33

任何方法都很好,并且可以理解不同的方法,但是优选简单的dplyr方法。谢谢!

编辑:我正在寻找一种方法,允许我一次为多个列执行此操作,并返回类似于上面显示的数据帧。< / p>

说我的数据被命名为&#39; df&#39;然后,我想一次性获取所有列的缺失比例,而无需再次手动输入名称。

以下代码不起作用,但它是我想要实现的一般概念。也许一个功能可能有所帮助,但我不确定我是如何接近它的。

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

4 个答案:

答案 0 :(得分:2)

以下是包含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

答案 1 :(得分:1)

您可以尝试这样的事情:

# 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
    }))

答案 2 :(得分:1)

假设您的数据位于数据框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

答案 3 :(得分:1)

我们也可以使用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]