【问题标题】:Summarizing count data as proportion in a data.frame将计数数据汇总为 data.frame 中的比例
【发布时间】:2017-01-05 08:45:59
【问题描述】:
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,但没有返回预期的结果。

【问题讨论】:

    标签: r summary


    【解决方案1】:

    另一种方法是计算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
    

    注意,灵感来自 @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
    

    【讨论】:

    • 没关系,当你是对我的帖子发表评论然后调整我的代码并将其发布到你的帖子时,这有点虚伪。
    【解决方案2】:

    我们可以尝试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
    

    【讨论】:

    • 谢谢,但如果一个问题全为 0,那么您的答案将无效。即dummy &lt;- data.frame(Q1 = c(0, 0, 0, 0), Q2 = c(1, 1, 0, 1), Q3 = c(0, 1, 1, 0))
    • @Adrian 实际上是这样,但方式不同。试试apply(dummy, 2, function(x) table(x)/length(x))
    【解决方案3】:

    我们可以通过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
    

    【讨论】:

    • 否则我猜你可以选择as.logical
    • 你知道你可以在其他人的答案下发表评论,而不是把它变成你的(以某种方式),比如在我的评论下“嘿,你也可以使用 colSums,把 0/1 变成合乎逻辑的” - 我想过这样做,但决定选择另一个选项,在 Ronak 的“嘿,你也只能调用 table 一次”下......这实际上是你应该做的......
    【解决方案4】:

    另一种方法是使用 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
    

    【讨论】:

    • 不完全是 OP 正在寻找的预期输出。
    【解决方案5】:

    不如上面的答案优雅:

    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
    

    【讨论】:

      【解决方案6】:

      一个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
      

      【讨论】:

        猜你喜欢
        • 2013-08-06
        • 1970-01-01
        • 1970-01-01
        • 2019-11-13
        • 2017-12-27
        • 1970-01-01
        • 2013-02-17
        • 2012-08-05
        • 2011-01-19
        相关资源
        最近更新 更多