2011-12-11 53 views
3

我很確定我正在複雜的事情。我有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 

回答

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 
+0

非常感謝!我認爲這就是我一直在尋找的。 –

+0

@Ramnath - 感謝在'reshape'和'reshape2'之間捕捉功能的改變。我沒有把任何人混淆,而是刪除了我的答案。另外,+1給你。 –

+0

@Josh。我想你應該保留你的答案。它非常優雅。你可以添加一個註釋,說明這個功能來自'reshape'並從'reshape2'丟棄。 – Ramnath

2

這裏是單獨使用reshape兩行的解決方案。缺省列名稱需要一些工作,但melt()cast()語句的語法很好表達。

一個重要的提示 - 不像reshapereshape2不能採取彙總函數名稱的矢量作爲其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 
+0

不錯的一個。注意hadley刪除了在'reshape2'中應用多個集合函數的這個特性。 – Ramnath

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