R reshape2 or dplyr/tidyr: 计算值占小计的百分比

R reshape2 or dplyr/tidyr: calculating values' percentage of sub-total

让我们以空气质量数据集为基础。

myaqm <- melt(airquality, id=c("Month", "Day"), na.rm = TRUE)

这简化了我的真实数据集。到目前为止,我已经这样做了:

myaqm_dcast <- dcast(myaqm, Day+variable~Month, value.var = "value", sum, margins=c("Day", "variable", "Month"))

这给了我这个:

> head(myaqm_dcast, n=10)
   Day variable     5     6     7     8     9  (all)
1    1    Ozone  41.0   0.0 135.0  39.0  96.0  311.0
2    1  Solar.R 190.0 286.0 269.0  83.0 167.0  995.0
3    1     Wind   7.4   8.6   4.1   6.9   6.9   33.9
4    1     Temp  67.0  78.0  84.0  81.0  91.0  401.0
5    1    (all) 305.4 372.6 492.1 209.9 360.9 1740.9
6    2    Ozone  36.0   0.0  49.0   9.0  78.0  172.0
7    2  Solar.R 118.0 287.0 248.0  24.0 197.0  874.0
8    2     Wind   8.0   9.7   9.2  13.8   5.1   45.8
9    2     Temp  72.0  74.0  85.0  81.0  92.0  404.0
10   2    (all) 234.0 370.7 391.2 127.8 372.1 1495.8

但是,我正在尝试为每个当前数字列创建一个额外的 variables'-percentage-of-days'-subtotal 列。所以我的目标是:

Day     variable        5       5(day %)        6       6(day %)        7       7(day %)        8       8(day %)        9       9(day %)        (all)       (all)(day %)
1       Ozone       41      13.4%       0       0.0%        135     27.4%       39      18.6%       96      26.6%       311     17.9%
1       Solar.R     190     62.2%       286     76.8%       269     54.7%       83      39.5%       167     46.3%       995     57.2%
1       Wind        7.4     2.4%        8.6     2.3%        4.1     0.8%        6.9     3.3%        6.9     1.9%        33.9        1.9%
1       Temp        67      21.9%       78      20.9%       84      17.1%       81      38.6%       91      25.2%       401     23.0%
1       (all)       305.4       100.0%      372.6       100.0%      492.1       100.0%      209.9       100.0%      360.9       100.0%      1740.9      100.0%
2       Ozone       36      15.4%       0       0.0%        49      12.5%       9       7.0%        78      21.0%       172     11.5%
2       Solar.R     118     50.4%       287     77.4%       248     63.4%       24      18.8%       197     52.9%       874     58.4%
2       Wind        8       3.4%        9.7     2.6%        9.2     2.4%        13.8        10.8%       5.1     1.4%        45.8        3.1%
2       Temp        72      30.8%       74      20.0%       85      21.7%       81      63.4%       92      24.7%       404     27.0%
2       (all)       234     100.0%      370.7       100.0%      391.2       100.0%      127.8       100.0%      372.1       100.0%      1495.8      100.0%

抱歉格式太糟糕了!但正如您希望看到的那样,新的附加列给出了当天和该月每个变量的百分比。

我发现另一个 Stack Overflow 助手建议使用 tidyr 和 dplyr,但我无法根据我的需要调整他们的示例。有人可以告诉我该怎么做吗?

我编写了一个百分比函数并将其与 dplyr 一起使用。然后我将列连接在一起。

pct <- function(x) {x/sum(x)}

df <- myaqm_dcast %>%
  filter(variable != "(all)") %>%
  group_by(Day) %>%
  mutate_each(funs(pct), 3:8) %>%
  inner_join(myaqm_dcast, by = c("Day", "variable"))

编辑:您可以修改百分比函数以根据需要进行打印(*100,粘贴 % 符号)。

编辑 2:如果您可以在没有(所有)行的情况下生活,我已经将其过滤掉了。您始终可以使用 summarise_each() 函数计算列总和。

为什么要重塑数据? Dataframe myaqm满足tidy data的要求(每一列是一个变量,每一行是一个观察值)。您可以按以下格式进行计算:

library(dplyr)
myaqm %>%
  group_by(Day, variable) %>%
  mutate(all = sum(value),
     perc = paste0(round(100 * value/all, 2), "%")

即使是创建绘图(例如通过 ggplot),这种格式也比重塑后的格式更适合。

如果确实有必要,您可以使用 tidyr/dplyr 进行整形:

...
gather(key, val, -c(Month:variable, all)) %>%
unite(temp, Month, key) %>%
spread(temp, val)