运行 table 依次为所有列

Run table for all columns in sequence

如果这是我的数据集

Id   Col_A_1   Col_A_2    Col_A_3    .....      Col_A_100
1    87        88         82                    88
2    88        82         82                    87
3    82        87         NA                    82
4    88        87         82                    88
5    87        87         87                    88

在从 Col_A_1 到 Col_A_100 的这些列上执行 table 函数的有效方法是什么?我试图避免 运行 table(df$Col_A_1 , useNA ="ifany")table(df$Col_A_2 , useNA ="ifany")、.... table(df$Col_A_100 , useNA ="ifany") 100次。

此外,如果可能的话,我喜欢保存在数据框中的输出。

预期输出

    Column         82        85     87       88     Missing
    Col_A_1        1         0      2        2            0   
    Col_A_2        1         0      3        1            0
    Col_A_3        3         0      1        0            1
    .
    .
    .
    Col_A_100      1         0      1        3            0

提前致谢。

# example data
d <- read.table(text = "
Id   Col_A_1   Col_A_2    Col_A_3   Col_A_100
1    87        88         82        88
2    88        82         82        87
3    82        87         NA        82
4    88        87         82        88
5    87        87         87        88", header = TRUE)

我刚刚创建了一个小tibble来使用和说明它。

Tibbles 本质上可以被认为是列表,所以 lapply 工作得很好。由于使用结果可能很麻烦,我将其作为列表条目放在小标题中:

library(dplyr)
x = tibble(col1 = sample(100,replace = T),
           col2 = sample(100,replace = T),
           col3 = sample(100,replace = T),
           col4 = sample(100,replace = T))

res = tibble(cols = colnames(x),
             tables = lapply(x, function(col) table(col, useNA = "ifany"))) 

# A tibble: 4 x 2
# cols  tables      
# <chr> <named list>
# col1  <table [61]>
# col2  <table [69]>
# col3  <table [60]>
# col4  <table [62]>

编辑:我没有注意到输出格式要求。可以这样做(可能有点不雅):

#I assume it is all numeric values
unique_names = sapply(res$tables, names) %>% purrr::reduce(union) #get all names present


unique_names_sorted = c(sort(as.numeric(unique_names)), if(any(is.na(unique_names))) "NA") # sort them by value and add in NA, if present

#create dummy matrix
mat = matrix(0, nrow = nrow(res), ncol = length(unique_names_sorted))
#assign corresponding names
colnames(mat) = unique_names_sorted
#populate dummy matrix
for (i in 1:nrow(mat)) {
  tmp = res$tables[[i]]
  if(any(is.na(names(tmp)))) names(tmp)[is.na(names(tmp))] = "NA"
  mat[,names(tmp)] = tmp
}

使用 stack 从 wide-to-long 中排除 Id 列重塑,然后 table 获取包括 NAs 在内的计数,transpose 将列名作为行,然后将 table object 转换为 dataframe:

data.frame(rbind(t(table(stack(d[, -1]), useNA = "always"))))
#           X82 X87 X88 NA.
# Col_A_1     1   2   2   0
# Col_A_2     1   3   1   0
# Col_A_3     3   1   0   1
# Col_A_100   1   1   3   0
# NA.         0   0   0   0