2014-10-03 85 views
0

鳞片状的水平,我有以下数据框:平均排由多种因素

df = data.frame(id=c("A","A","A","A","B","B","B","B","C","C","C","C","D","D","D","D"), 
       sub=rep(c(1:4),4), 
       acc1=runif(16,0,3), 
       acc2=runif(16,0,3), 
       acc3=runif(16,0,3), 
       acc4=runif(16,0,3)) 

我想要的是获取每个ID,这就是我想要获得平均ACC1,ACC2平均行, acc3和acc4的每个级别A,B,C和D的平均值(每个id的4个级别),最终会给出类似的结果(当然我会用当然的方式替换NAs) :

dfavg = data.frame(id=c("A","B","C","D"),meanacc1=NA,meanacc2=NA,meanacc3=NA,meanacc4=NA) 

在此先感谢!

回答

3

尝试:

你可以使用任何专门的包dplyrdata.table或使用base R的。因为您有很多以acc开头的列来表示平均值,所以我选择dplyr。在这里,思想是首先groupid然后用summarise_each获得每一列的mean变量通过id使用paste

# colnames(df1)[-1] <- paste0("mean", colnames(df1)[-1]) 

给出结果是STARTS_WITH acc

library(dplyr) 
df1 <- df %>% 
      group_by(id) %>% 
      summarise_each(funs(mean=mean(., na.rm=TRUE)), starts_with("acc")) %>% 
      rename(meanacc1=acc1, meanacc2=acc2, meanacc3=acc3, meanacc4=acc4) #this works but it requires more typing. 

我会rename

# id meanacc1 meanacc2 meanacc3 meanacc4 
#1 A 1.7061929 2.401601 2.057538 1.643627 
#2 B 1.7172095 1.405389 2.132378 1.769410 
#3 C 1.4424233 1.737187 1.998414 1.137112 
#4 D 0.5468509 1.281781 1.790294 1.429353 

或者u唱data.table

library(data.table) 
nm1 <- paste0("acc", 1:4) #names of columns to do the `means` 
dt1 <- setDT(df)[, lapply(.SD, mean, na.rm=TRUE), by=id, .SDcols=nm1] 

这里.SD意味着Subset of Data.table.SDcols都列到我们应用mean操作。

setnames(dt1, 2:5, paste0("mean", nm1)) #change the names of the concerned columns in the result 
dt1 
+0

+1,我刚刚看到帖子和我脑海中的代码。太晚了。你将如何编写'rename()'部分? – jazzurro 2014-10-03 16:59:40

+0

@jazzurro谢谢,昨天,当我尝试'重命名'它不工作有一些奇怪的原因。也许我做错了什么。我使用'rename'更新了这篇文章,尽管在重命名多个变量时需要更多的输入。我更喜欢沿''rename(paste0(“mean”,starts_with(“acc”)= starts_with(“acc”))''的方向行事,尽管它不起作用 – akrun 2014-10-04 04:29:04

+0

@jazzuro谢谢,它完美的工作!对不起 – 2014-10-07 18:11:31

0

可以在基本包本身使用该这样做:

a <- list(); 

for (i in 1:nlevels(df$id)) 
{  
    a[[i]] = colMeans(subset(df, id==levels(df$id)[i])[,c(3,4,5,6)]) ##select columns of df of which you want to compute the means. In your example, 3, 4, 5 and 6 are the columns 
} 
meanDF <- cbind(data.frame(levels(df$id)), data.frame(matrix(unlist(a), nrow=4, ncol=4, byrow=T))) 

colnames(meanDF) = c("id", "meanacc1", "meanacc2", "meanacc3", "meanacc4") 
meanDF 

id meanacc1 meanacc2 meanacc3 meanacc4 
A 1.464635 1.645898 1.7461862 1.026917 
B 1.807555 1.097313 1.7135346 1.517892 
C 1.350708 1.922609 0.8068907 1.607274 
D 1.458911 0.726527 2.4643733 2.141865 
2

(这必须被要求至少20倍。)的'聚合函数应用相同的函数(给出的第三个参数),以它的第一个参数的所有列由它的第二个参数定义的组内:

aggregate(df[-(1:2)], df[1],mean) 

如果要追加的字母“意为”列名:

names(df2) <- paste0("mean", names(df2) 

如果你本来想自动完成列选择用grep然后或grepl将工作:

aggregate(df[ grepl("acc", names(df))], df[1], mean) 
+0

当然,'aggregate'的''''方法':'aggregate(。〜id,df [-2],mean)'。 – A5C1D2H2I1M1N2O1R2T1 2014-10-03 17:14:04

+0

对,我一直忘记公式方法它与其他基本概括函数('tapply',''''''ave')有一些不同,它们有三个参数:数据,索引,函数顺序,即使明显不那么'优雅'出于某种原因,我不会忘记'xtabs.formula'函数。 – 2014-10-03 17:39:00

1

这里有一对夫妇的其他基础R选项:

split + vapply(因为我们知道vapply将简化到尽可能矩阵)

t(vapply(split(df[-c(1, 2)], df[, 1]), colMeans, numeric(4L))) 

by(用do.call(rbind, ...)得到最终的结构)

do.call(rbind, by(data = df[-c(1, 2)], INDICES = df[[1]], FUN = colMeans)) 

都将会给你的东西像这样作为你的结果:

#  acc1  acc2  acc3  acc4 
# A 1.337496 2.091926 1.978835 1.799669 
# B 1.287303 1.447884 1.297933 1.312325 
# C 1.870008 1.145385 1.768011 1.252027 
# D 1.682446 1.413716 1.582506 1.274925 

这里使用的样品数据为(与set.seed,可重复性):

set.seed(1) 
df = data.frame(id = rep(LETTERS[1:4], 4), 
       sub = rep(c(1:4), 4), 
       acc1 = runif(16, 0, 3), 
       acc2 = runif(16, 0, 3), 
       acc3 = runif(16, 0, 3), 
       acc4 = runif(16, 0, 3)) 

向上扩展至1M行,这些都表现相当好(虽然他们显然没有那么快,因为“dplyr”或“ data.table“)。