转置data.frame并计算每列的非NA值

时间:2019-03-13 19:30:03

标签: r dplyr lapply data-manipulation

我有这个数据框:

set.seed(100)
x <- data.frame(KAS1_1 = sample(c(letters[1], NA), 10, replace =TRUE),
                KAS1_2 = sample(c(letters[2], NA), 10, replace =TRUE),
                KAS1_3 = sample(c(letters[3], NA), 10, replace =TRUE),
                KAS1_4 = sample(c(letters[4], NA), 10, replace =TRUE),
                KAS1_5 = sample(c(letters[5], NA), 10, replace =TRUE),
                stringsAsFactors = FALSE)
> df
   KAS1_1 KAS1_2 KAS1_3 KAS1_4 KAS1_5
1       a   <NA>   <NA>      d      e
2       a   <NA>   <NA>   <NA>   <NA>
3    <NA>      b   <NA>      d   <NA>
4       a      b   <NA>   <NA>   <NA>
5       a   <NA>      c   <NA>   <NA>
6       a   <NA>      c   <NA>      e
7    <NA>      b   <NA>      d   <NA>
8       a      b   <NA>   <NA>   <NA>
9    <NA>      b   <NA>   <NA>      e
10      a   <NA>      c      d      e

我正在寻找一种方法来获得此信息:

   Var   Count
KAS1_1   8
KAS1_2   5
KAS1_3   3
KAS1_4   4
KAS1_5   4

我正在尝试使用dplyrtablelapply()使用t(),但没有结果。有没有更直接的方法?

2 个答案:

答案 0 :(得分:5)

## halfway there
colSums(!is.na(x))
# KAS1_1 KAS1_2 KAS1_3 KAS1_4 KAS1_5 
#      7      5      3      4      4 

## make it a data frame
data.frame(count = colSums(!is.na(x)))
#        count
# KAS1_1     7
# KAS1_2     5
# KAS1_3     3
# KAS1_4     4
# KAS1_5     4

## or use `stack` like markus's nice answer:
stack(colSums(!is.na(x)))
#   values    ind
# 1      7 KAS1_1
# 2      5 KAS1_2
# 3      3 KAS1_3
# 4      4 KAS1_4
# 5      4 KAS1_5

将行名称转换为其自己的列将是另一步骤,但我将留给您。

tidyverse解决方案可以让您转换为长格式,然后进行分组求和:

library(dplyr)
library(tidyr)
x %>% gather %>%
  group_by(key) %>%
  summarize(value = sum(!is.na(value)))
# # A tibble: 5 x 2
#   key    value
#   <chr>  <int>
# 1 KAS1_1     7
# 2 KAS1_2     5
# 3 KAS1_3     3
# 4 KAS1_4     4
# 5 KAS1_5     4

一种data.table解决方案将是类似的:

library(data.table)
xdt = as.data.table(x)
melt(xdt, measure.vars = names(xdt))[, .(count = sum(!is.na(value))), by = .(variable)]
#    variable count
# 1:   KAS1_1     7
# 2:   KAS1_2     5
# 3:   KAS1_3     3
# 4:   KAS1_4     4
# 5:   KAS1_5     4

答案 1 :(得分:3)

基本R选项

stack(lapply(x, function(y) length(na.omit(y))))
#  values    ind
#1      7 KAS1_1
#2      5 KAS1_2
#3      3 KAS1_3
#4      4 KAS1_4
#5      4 KAS1_5

除了Gregor的解决方案外,另一个tidyverse选项是

library(dplyr); library(tidyr)
gather(x, na.rm = TRUE) %>% count(key)