将计数数据汇总为 data.frame 中的比例

Summarizing count data as proportion in a data.frame

dummy <- data.frame(Q1 = c(0, 1, 0, 1),
                    Q2 = c(1, 1, 0, 1),
                    Q3 = c(0, 1, 1, 0))
df_dummy <- data.frame(Question = c("Q1", "Q2", "Q3"),
                       X1 = c(2/4, 3/4, 2/4),
                       X0 = c(2/4, 1/4, 2/4))

> dummy
  Q1 Q2 Q3
1  0  1  0
2  1  1  1
3  0  0  1
4  1  1  0

> df_dummy
  Question   X1   X0
1       Q1 0.50 0.50
2       Q2 0.75 0.25
3       Q3 0.50 0.50

我有一些数据 (dummy),其中我对 Q1、Q2 和 Q3 有二进制响应。我想以 df_dummy 中所示的格式总结我的数据,其中对于每个问题,第 X1 列告诉我回答 1 到 Q1 的人数比例,第 X0 列告诉我回答 0 到 Q0 的人的比例。我尝试了 prop.table 但没有 return 想要的结果。

我们可以尝试 applymargin =2 并将每个值的计数除以列中的总长度

t(apply(dummy, 2, function(x) table(x)/length(x)))

#     0    1
#Q1 0.50 0.50
#Q2 0.25 0.75
#Q3 0.50 0.50

我们可以用 tableprop.table

来做到这一点
t(sapply(dummy, function(x) prop.table(table(x))))
#     0    1
#Q1 0.50 0.50
#Q2 0.25 0.75
#Q3 0.50 0.50

或者更有效的方法是调用 table 一次

prop.table(table(stack(dummy)[2:1]),1)
#   values
#ind     0    1
#  Q1 0.50 0.50
#  Q2 0.25 0.75
#  Q3 0.50 0.50

或者另一种选择是 colMeans(灵感来自@Cath 对 colSums 的使用)

X0 <- colMeans(!dummy)
data.frame(X1 = 1 - X0, X0)
#    X1   X0
#Q1 0.50 0.50
#Q2 0.75 0.25
#Q3 0.50 0.50

不如上面的答案优雅:

d <- t(dummy)
cbind(X0 = (ncol(d) - rowSums(d)) / ncol(d), X1 = rowSums(d) / ncol(d))

或者,为了避免两次计算相同的东西,并得到一个数据框:

d <- t(dummy)
i <- ncol(d)
j <- rowSums(d)
data.frame(Question = rownames(d), X0 = (i - j) / i, X1 = j / i)

好了:

   Question   X0   X1
Q1       Q1 0.50 0.50
Q2       Q2 0.25 0.75
Q3       Q3 0.50 0.50

另一种方法是计算1s的比例,然后从中推导出0s的比例:

X1 <- colSums(dummy==1)/nrow(dummy)
df_dummy <- data.frame(X1, X0=1-X1)
df_dummy
#     X1   X0
#Q1 0.50 0.50
#Q2 0.75 0.25
#Q3 0.50 0.50

NB,灵感来自@akrun 的 ColMeans 想法: 您也可以使用 colMeans 而不是将 colSums 除以定义 X1 的行:

X1 <- colMeans(dummy==1)
df_dummy <- data.frame(X1, X0=1-X1)
df_dummy
#     X1   X0
#Q1 0.50 0.50
#Q2 0.75 0.25
#Q3 0.50 0.50

另一种方法是使用 do.call & lapply

do.call(cbind,lapply(dummy,function(x) data.frame(table(x))[,2]))
#    Q1 Q2 Q3
[1,]  2  1  2
[2,]  2  3  2

一个 tidyverse 选项:

library(tidyr)
library(janitor)

dummy %>%
  gather(question, val) %>%    # reshape to long form
  tabyl(question, val) %>%    # make crosstab table
  adorn_percentages("row") %>%
  clean_names() 



 question   x0   x1
       Q1 0.50 0.50
       Q2 0.25 0.75
       Q3 0.50 0.50