简化创建汇总表的过程

时间:2011-12-11 00:20:30

标签: r

我很确定我的事情变得复杂了。我有一个包含p个变量的数据框(此处为:v1v3)和两个因子变量(此处为:sexunemp):

> 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

3 个答案:

答案 0 :(得分:5)

这是一种方法

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

答案 1 :(得分: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

答案 2 :(得分:1)

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

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))