我的数据框包含五个变量。其中两个是度量标准测量,其中三个包含作为因子存储的组。我尝试通过不同的组在一个循环中将该数据帧三次子集化,并计算每个组的每个度量测量的平均值。结果可以作为新数据帧存储在新列表中。目前我使用了subset
包中的ldply
和plyr
。单个子集没有问题但是当我尝试将循环中的结果存储在向量中时,我收到一条警告消息,指出number of items to replace is not a multiple of replacement length
。下面是一个示例代码。任何帮助将不胜感激!
df<-data.frame(a=c(1:5),b=c(21:25),group1=c("a","b","a","a","b"),group2=c("b","a","c","b","c"),group3=c("a","b","c","d","c"))
# single subset
llply(subset(df,group1=="a")[1:2],mean)
# subset for all groups
# create grouplist
grouplist<-colnames(df[3:5])
# create vector to store results
output.vector<-vector()
# create loop
for (i in grouplist)output.vector[i]<-ldply(subset(df,grouplist=="a")[1:2],mean)
output.vector
Warning messages:
1: In output.vector[i] <- ldply(subset(df, grouplist == "a")[1:2], :
number of items to replace is not a multiple of replacement length
所以列表中一个项目的输出如下所示:
output.vector$group1
|a| | b|
|a| |2.67| |3.5|
|b| |22.7| |23.5|
output.vector$group2
|a| | b| |c|
|a| |2| |2.5| |4|
|b| |22| |22.5| |24|
output.vector$group3
|a| |b| |c| |d|
|a| |1| |2| |4| |4|
|b| |21| |22| |24| |14|
答案 0 :(得分:3)
使用by
和colMeans
的基本包中的另一个选项,并循环遍历组列:
id.group <- grepl('group',colnames(df))
lapply(df[,id.group],
function(x){
res <- by(df[,!id.group],x,colMeans)
do.call(rbind,res)
})
$group1
a b
a 2.666667 22.66667
b 3.500000 23.50000
$group2
a b
a 2.0 22.0
b 2.5 22.5
c 4.0 24.0
$group3
a b
a 1 21
b 2 22
c 4 24
d 4 24
编辑添加一些基准
library(microbenchmark)
microbenchmark(ag(),dr(),an())
Unit: milliseconds
expr min lq median uq max neval
ag() 4.717987 4.936251 5.072595 5.394017 27.13639 100
dr() 14.676580 15.244331 15.689392 16.252781 43.76198 100
an() 14.691750 15.159945 15.625107 16.312705 46.01326 100
看起来agstudy解决方案是胜利者,比其他2个解决方案快3倍!
这里使用的功能:
ag <- function(){
id.group <- grepl('group',colnames(df))
lapply(df[,id.group],
function(x){
res <- by(df[,!id.group],x,colMeans)
do.call(rbind,res)
})
}
dr <- function(){
grouplist<-colnames(df[3:5])
lapply(grouplist, function(n)
daply(df, n, function(d) colMeans(d[, 1:2])))
}
an <- function(){
temp <- melt(df, id.vars=1:2)
setNames(
lapply(unique(temp$variable), function(x) {
aggregate(. ~ value, temp[temp$variable == x, c(1, 2, 4)], mean)
}), unique(temp$variable))
}
答案 1 :(得分:2)
一种方法是先将数据转换为长格式,然后使用lapply
和aggregate
。
以下是长篇数据。
library(reshape2)
temp <- melt(df, id.vars=1:2)
temp
# a b variable value
# 1 1 21 group1 a
# 2 2 22 group1 b
# 3 3 23 group1 a
# 4 4 24 group1 a
# 5 5 25 group1 b
# 6 1 21 group2 b
# 7 2 22 group2 a
# 8 3 23 group2 c
# 9 4 24 group2 b
# 10 5 25 group2 c
# 11 1 21 group3 a
# 12 2 22 group3 b
# 13 3 23 group3 c
# 14 4 24 group3 d
# 15 5 25 group3 c
这是计算。我相信你感兴趣的所有计算都在那里。
setNames(
lapply(unique(temp$variable), function(x) {
aggregate(. ~ value, temp[temp$variable == x, c(1, 2, 4)], mean)
}), unique(temp$variable))
# $group1
# value a b
# 1 a 2.666667 22.66667
# 2 b 3.500000 23.50000
#
# $group2
# value a b
# 1 a 2.0 22.0
# 2 b 2.5 22.5
# 3 c 4.0 24.0
#
# $group3
# value a b
# 1 a 1 21
# 2 b 2 22
# 3 c 4 24
# 4 d 4 24
答案 2 :(得分:2)
可以使用lapply
包中daply
和plyr
的组合来完成此操作:
grouplist<-colnames(df[3:5])
lapply(grouplist, function(n) daply(df, n, function(d) colMeans(d[, 1:2])))
# [[1]]
#
# group1 a b
# a 2.666667 22.66667
# b 3.500000 23.50000
#
# [[2]]
#
# group2 a b
# a 2.0 22.0
# b 2.5 22.5
# c 4.0 24.0
#
# [[3]]
#
# group3 a b
# a 1 21
# b 2 22
# c 4 24
# d 4 24