【问题标题】:Simplifying the process of creating a summary table简化创建汇总表的过程
【发布时间】:2017-05-04 02:16:05
【问题描述】:

我很确定我把事情复杂化了。我有一个带有 p 变量(这里:v1 到 v3)和两个因子变量(这里:sex 和 unemp)的数据框:

> head(df)
  sex unemp v1 v2 v3
1   0     0  2  4  4
2   0     0  2  1  1
3   1     0  3  3  5
4   1     1  2  3  5
5   0     0  1  2  5
6   1     0  3  5  4

我现在想修改(即计算中位数和平均值,然后重新排列汇总表)我的数据,使生成的数据框看起来像这样(对于男性或女性):

> df.res.men
   median.unemp.1 median.unemp.0 mean.unemp.1 mean.unemp.0
v1            2.0            2.0     2.666667     2.391304
v2            2.0            3.5     2.500000     3.369565
v3            4.5            3.0     4.166667     2.956522

这里是完整的代码:

library(plyr)
## generate data
set.seed(1)
df <- data.frame(sex=rbinom(100, 1, 0.5),
                 unemp=rbinom(100, 1, 0.2),
                 v1=sample(1:5, 100, replace=TRUE),
                 v2=sample(1:5, 100, replace=TRUE),
                 v3=sample(1:5, 100, replace=TRUE)
                 )
head(df)

## compute mean and median for all variables by sex and unemp
df.mean <- ddply(df, .(unemp, sex), .fun=colMeans, na.rm=TRUE)
df.mean
df.median <- ddply(df, .(unemp, sex), .fun=function(x)apply(x,2,median, na.rm=TRUE))
df.median

## rearrange summary table
df.res.men <- cbind(t(subset(df.median, sex==0 & unemp==1)),
                 t(subset(df.median, sex==0 & unemp==0)),
                 t(subset(df.mean, sex==0 & unemp==1)),
                 t(subset(df.mean, sex==0 & unemp==0)))
df.res.men <- df.res.men[-c(1:2),]
colnames(df.res.men) <- c("median.unemp.1", "median.unemp.0", 
                          "mean.unemp.1", "mean.unemp.0")
df.res.men

【问题讨论】:

    标签: r


    【解决方案1】:

    这是一种方法

    library(plyr); library(reshape2)
    dfm <- melt(df, id = c('sex', 'unemp'))
    df2 <- ddply(dfm, .(variable, unemp, sex), summarize, 
      avg = mean(value), med = median(value))
    
    df2m <- melt(df2, id = 1:3, variable.name = 'sum_fun')
    df_0 <- dcast(df2m, sex + variable ~ sum_fun + unemp, subset = .(sex == 0))
    
       sex variable    avg_0  avg_1 med_0 med_1
    1   0       v1 2.794872 3.0000     3   3.5
    2   0       v2 3.102564 2.8750     3   3.0
    3   0       v3 3.205128 3.1875     3   4.0
    

    【讨论】:

    • 非常感谢!我想这就是我一直在寻找的。​​span>
    • @Ramnath -- 感谢您发现 reshape 和 reshape2 之间的功能变化。我没有混淆任何人,而是删除了我的答案。另外,+1 给你的。
    • @Josh。我认为你应该保留你的答案。它非常优雅。您可以添加一条注释,明确该功能来自 reshape 并从 reshape2 删除。
    • @Ramnath -- 你是对的。把答案留在那里很好,所以我现在已经“揭开了”它的面纱。
    【解决方案2】:

    这是一个单独使用reshape 的两行解决方案。默认列名需要做一些工作,但melt() 和cast() 语句的语法很好表达。

    (一个重要提示 -- 与reshape 不同,reshape2 不能将摘要函数名称的向量作为其fun.aggregate 参数,正如我在下面使用c(mean, median) 所做的那样. 感谢 Ramnath 指出这一点。)

    library(reshape)
    dmelt <- melt(df, id=c('sex', 'unemp'))
    
    # Results for sex 0
    cast(dmelt, variable ~ unemp, c(mean, median), subset = sex==0)
    #   variable   0_mean 0_median   1_mean 1_median
    # 1       v1 2.391304      2.0 2.666667      2.0
    # 2       v2 3.369565      3.5 2.500000      2.0
    # 3       v3 2.956522      3.0 4.166667      4.5
    
    # Results for sex 1
    cast(dmelt, variable ~ unemp, c(mean, median), subset = sex==1)
    #   variable   0_mean 0_median   1_mean 1_median
    # 1       v1 3.027778        3 2.416667      2.0
    # 2       v2 2.638889        2 2.750000      3.0
    # 3       v3 3.027778        3 2.583333      2.5
    

    【讨论】:

    • 不错的一个。请注意,hadley 在reshape2 中删除了应用多个聚合函数的这一特性。
    【解决方案3】:

    无需重塑数据的解决方案。

    f <- function(x) rbind(each(mean,median)(na.omit(x)))
    #
    # This should work but it doesn't.
    # It almost work except labelling output with function names
    #
    df.res <- ddply(df,.(unemp, sex),.fun=numcolwise(f))
    #
    # Some workaround
    #
    df.res <- dlply(df,.(unemp, sex),.fun=numcolwise(f))
    df.res <- cbind(attr(df.res,"split_labels"),do.call(rbind,df.res))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 2015-09-28
      • 2021-12-14
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多