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

Chr*_*ris 3 r data-manipulation lapply dplyr

我有这个数据框:

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
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种方法来做到这一点:

   Var   Count
KAS1_1   8
KAS1_2   5
KAS1_3   3
KAS1_4   4
KAS1_5   4
Run Code Online (Sandbox Code Playgroud)

我试图与dplyr使用table,并lapply()t()没有结果。有没有更直接的方法?

Gre*_*gor 6

## 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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

一个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
Run Code Online (Sandbox Code Playgroud)