【问题标题】:ddply summarise proportional countddply 汇总比例计数
【发布时间】:2013-08-06 02:18:41
【问题描述】:

我在使用 plyr 包中的 ddply 函数时遇到了一些问题。我试图用每组内的计数和比例来总结以下数据。这是我的数据:

    structure(list(X5employf = structure(c(1L, 3L, 1L, 1L, 1L, 3L, 
1L, 1L, 1L, 3L, 1L, 1L, 1L, 2L, 2L, 3L, 3L, 3L, 1L, 2L, 2L, 2L, 
2L, 2L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 3L, 2L, 1L, 1L, 3L, 1L, 
3L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 
3L, 3L, 1L), .Label = c("increase", "decrease", "same"), class = "factor"), 
    X5employff = structure(c(2L, 6L, NA, 2L, 4L, 6L, 5L, 2L, 
    2L, 8L, 2L, 2L, 2L, 7L, 7L, 8L, 11L, 7L, 2L, 8L, 8L, 11L, 
    7L, 6L, 2L, 5L, 2L, 8L, 7L, 7L, 7L, 8L, 6L, 7L, 5L, 5L, 7L, 
    2L, 6L, 7L, 2L, 2L, 2L, 2L, 2L, 5L, 5L, 5L, 2L, 5L, 2L, 2L, 
    2L, 5L, 12L, 2L, 2L, 2L, 2L, 5L, 5L, 5L, 5L, 2L, 5L, 2L, 
    13L, 9L, 9L, 9L, 7L, 8L, 5L), .Label = c("", "1", "1  and 8", 
    "2", "3", "4", "5", "6", "6 and 7", "6 and 7 ", "7", "8", 
    "1 and 8"), class = "factor")), .Names = c("X5employf", "X5employff"
), row.names = c(NA, 73L), class = "data.frame")

这是我使用 ddply 的电话:

ddply(kano_final, .(X5employf, X5employff), summarise, n=length(X5employff), prop=(n/sum(n))*100)

这给了我正确的X5employff 的每个实例的计数,但似乎是在每一行而不是在因子X5employf 的每个级别内计算比例,如下所示:

   X5employf X5employff  n prop
1   increase          1 26  100
2   increase          2  1  100
3   increase          3 15  100
4   increase    1 and 8  1  100
5   increase       <NA>  1  100
6   decrease          4  1  100
7   decrease          5  5  100
8   decrease          6  2  100
9   decrease          7  1  100
10  decrease          8  1  100
11      same          4  4  100
12      same          5  6  100
13      same          6  5  100
14      same    6 and 7  3  100
15      same          7  1  100

当手动计算每组内的比例时,我得到了这个:

   X5employf X5employff  n prop
1   increase          1 26  59.09
2   increase          2  1  2.27
3   increase          3 15  34.09
4   increase    1 and 8  1  2.27
5   increase       <NA>  1  2.27
6   decrease          4  1  10.00
7   decrease          5  5  50.00
8   decrease          6  2  20.00
9   decrease          7  1  10.00
10  decrease          8  1  10.00
11      same          4  4  21.05
12      same          5  6  31.57
13      same          6  5  26.31
14      same    6 and 7  3  15.78
15      same          7  1  5.26

如您所见,因子 X5employf 的每个水平的比例总和等于 100。

我知道这可能非常简单,但尽管阅读了各种类似的帖子,但我似乎无法理解它。任何人都可以帮助解决这个问题以及我对汇总功能如何工作的理解吗?!

非常感谢

马蒂

【问题讨论】:

  • 事实证明sum(n) 没有按预期计算

标签: r plyr


【解决方案1】:

您不能在一个 ddply 调用中执行此操作,因为传递给每个 summarize 调用的是您的组变量特定组合的数据子集。在此最低级别,您无权访问该中间级别sum(n)。相反,分两步完成:

kano_final <- ddply(kano_final, .(X5employf), transform,
                    sum.n = length(X5employf))

ddply(kano_final, .(X5employf, X5employff), summarise, 
      n = length(X5employff), prop = n / sum.n[1] * 100)

编辑:使用单个 ddply 调用并使用 table,正如您所暗示的那样:

ddply(kano_final, .(X5employf), summarise,
      n          = Filter(function(x) x > 0, table(X5employff, useNA = "ifany")),
      prop       = 100* prop.table(n),
      X5employff = names(n))

【讨论】:

  • 感谢弗洛德尔,这正是我想要的。无论如何将其组合成一个电话?我试图总结一个相当大的数据集,并试图达到可以为此编写脚本的地步,所以在每种情况下,我只需要输入一个分组变量和一个“测量”变量,有点像这个例子计算数据集中组的置信区间:cookbook-r.com/Manipulating_data/Summarizing_data
  • 哦,仍然不能完全确定“转换”和“总结”之间的区别!?
  • transform 添加到数据的每一行(就像基本的ave 函数一样),而summarize 将聚合您的数据(就像基本的aggregate 函数一样)。跨度>
【解决方案2】:

我将在此处添加一个 dplyr 示例,它使用短代码和易于阅读的语法,一步即可轻松完成。

d 是你的 data.frame

library(dplyr)
d%.%
  dplyr:::group_by(X5employf, X5employff) %.%
  dplyr:::summarise(n = length(X5employff)) %.%
  dplyr:::mutate(ngr = sum(n)) %.% 
  dplyr:::mutate(prop = n/ngr*100)

会导致

Source: local data frame [15 x 5]
Groups: X5employf

   X5employf X5employff  n ngr      prop
1   increase          1 26  44 59.090909
2   increase          2  1  44  2.272727
3   increase          3 15  44 34.090909
4   increase    1 and 8  1  44  2.272727
5   increase         NA  1  44  2.272727
6   decrease          4  1  10 10.000000
7   decrease          5  5  10 50.000000
8   decrease          6  2  10 20.000000
9   decrease          7  1  10 10.000000
10  decrease          8  1  10 10.000000
11      same          4  4  19 21.052632
12      same          5  6  19 31.578947
13      same          6  5  19 26.315789
14      same    6 and 7  3  19 15.789474
15      same          7  1  19  5.263158

【讨论】:

    【解决方案3】:

    您显然想要做的是找出每个 X5employf 值的 X5employff 比例。但是,您不会告诉 ddply X5employf 和 X5employff 是不同的;对于 ddply,这两个变量只是拆分数据的两个变量。此外,由于每行有一个观察值,即每行数据的计数 = 1,因此每个 (X5employf, X5employff) 组合的长度等于每个 (X5employf, X5employff) 组合的总和。

    我能想到的解决您问题的最简单的“plyr方法”如下:

    result <- ddply(kano_final, .(X5employf, X5employff), summarise, n=length(X5employff), drop=FALSE)
    n <- result$n
    n2 <- ddply(kano_final, .(X5employf), summarise, n=length(X5employff))$n
    result <- data.frame(result, prop=n/rep(n2, each=13)*100)
    

    你也可以使用旧的 xtabs:

    a <- xtabs(~X5employf + X5employff, kano_final)
    b <- xtabs(~X5employf, kano_final)
    a/matrix(b, nrow=3, ncol=ncol(a))
    

    【讨论】:

    • 你的 plyr 解决方案和@flodel 有什么区别?
    • 我看到的一个区别是我不使用硬编码的each = 13。这不能很好地概括......
    • 谢谢两位,这让我更接近了解发生了什么。我发现这看起来更简单,但我真的不明白发生了什么:df.new&lt;-ddply(kano_final,.(X5employf),summarise, prop=prop.table(table(X5employff)), X5employff=names(table(X5employff))) 虽然它似乎工作......但没有添加“计数”列。我应该提到这一切背后的原因,以便我可以使用 ggplot2 或类似工具绘制结果的频率计数或频率百分比条形图......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多