在多个数据框中计算平均值。

7
我希望使用R来绘制不同数据库系统性能评估结果的图表。对于每个系统,我加载了相同的数据,并在多次迭代中执行相同的查询。
单个系统的数据如下:
"iteration", "lines", "loadTime", "query1", "query2", "query3"
1, 100000, 120.4, 0.5, 6.4, 1.2
1, 100000, 110.1, 0.1, 5.2, 2.1
1, 50000, 130.3, 0.2, 4.3, 2.2

2, 100000, 120.4, 0.1, 2.4, 1.2
2, 100000, 300.2, 0.2, 4.5, 1.4
2, 50000, 235.3, 0.4, 4.2, 0.5

3, 100000, 233.5, 0.7, 8.3, 6.7
3, 100000, 300.1, 0.9, 0.5, 4.4
3, 50000, 100.2, 0.4, 9.2, 1.2

我现在需要的(用于绘图)是一个包含这些测量值平均值的矩阵或数据框。

目前我正在执行以下操作:

# read the file
all_results <- read.csv(file="file.csv", head=TRUE, sep=",")

# split the results by iteration
results <- split(all_results, all_results$iteration)

# convert each result into a data frane
r1 = as.data.frame(results[1])
r2 = as.data.frame(results[2])
r3 = as.data.frame(results[3])

# calculate the average
(r1 + r2 +r3) / 3

我可以把所有内容放进一个函数中,在for循环中计算平均矩阵,但我感觉应该有一种更优雅的解决方案。你有什么想法吗?
对于只有部分结果的情况,例如某次迭代的行数小于其他情况下的行数,我该怎么办呢?
谢谢!
5个回答

4
如果我理解正确,对于给定的数据库系统,在每个“迭代”(1...N)中,您正在加载一系列数据集(1、2、3)并在其上运行查询。看起来您想要计算所有迭代中每个数据集的平均时间。如果是这样,实际上您需要在all_results表中添加一个额外的列DataSet来标识数据集。我们可以按照以下方式添加此列:
all_results <- cbind( data.frame( DataSet = rep(1:3,3) ), all_results )
> all_results
  DataSet iteration  lines loadTime query1 query2 query3
1       1         1 100000    120.4    0.5    6.4    1.2
2       2         1 100000    110.1    0.1    5.2    2.1
3       3         1  50000    130.3    0.2    4.3    2.2
4       1         2 100000    120.4    0.1    2.4    1.2
5       2         2 100000    300.2    0.2    4.5    1.4
6       3         2  50000    235.3    0.4    4.2    0.5
7       1         3 100000    233.5    0.7    8.3    6.7
8       2         3 100000    300.1    0.9    0.5    4.4
9       3         3  50000    100.2    0.4    9.2    1.2

现在,您可以使用plyr包中的ddply函数轻松提取每个数据集的负载和查询时间的平均值。
> ddply(all_results, .(DataSet), colwise(mean, .(loadTime, query1, query2)))
  DataSet loadTime    query1 query2
1       1 158.1000 0.4333333    5.7
2       2 236.8000 0.4000000    3.4
3       3 155.2667 0.3333333    5.9

顺便提一下,我强烈建议您查看Hadley Wickham的plyr,其中包含丰富的数据操作函数。


这确实比for循环更优雅...感谢提示。 - behas
如果我想在ddply的输出框架中包含“lines”列怎么办?我可以通过同时计算行数的平均值来实现这一点;但是这样做似乎没有意义,因为行号是静态值; - behas
我明白你的意思,但是我想取一堆相同值的“平均”应该没有什么坏处! - Prasad Chalasani

3
我不明白为什么需要通过iteration来拆分all_results。你可以直接对all_results使用aggregate。并不需要所有的迭代都拥有相同数量的观测值。
Lines <- "iteration, lines, loadTime, query1, query2, query3
1, 100000, 120.4, 0.5, 6.4, 1.2
1, 100000, 110.1, 0.1, 5.2, 2.1
1, 50000, 130.3, 0.2, 4.3, 2.2
2, 100000, 120.4, 0.1, 2.4, 1.2
2, 100000, 300.2, 0.2, 4.5, 1.4
2, 50000, 235.3, 0.4, 4.2, 0.5
3, 100000, 233.5, 0.7, 8.3, 6.7
3, 100000, 300.1, 0.9, 0.5, 4.4
3, 50000, 100.2, 0.4, 9.2, 1.2"

all_results <- read.csv(textConnection(Lines))

aggregate(all_results[,-1], by=all_results[,"iteration",drop=FALSE], mean)

我认为OP需要按照数据集进行平均,就像我在我的答案中所说的那样,而不是按照“迭代”进行平均(对于一个有100000行和一个有50000行的数据集取平均值是没有意义的)。至少这是我对他真正想做的事情的理解。 - Prasad Chalasani
...дҪҶжҳҜдҪҝз”Ёaggregateзҡ„жғіжі•еҫҲеҘҪпјҲ+1пјүгҖӮжҲ‘еҸӘжҳҜжғіжҠҠиҝҷдёӘдҪңдёәз»ғд№ дҪҝз”ЁplyrгҖӮ - Prasad Chalasani

1

试试这个:

> Reduce("+", results) / length(results)
  DataSet iteration lines loadTime    query1 query2   query3
1       1         2 1e+05 158.1000 0.4333333    5.7 3.033333
2       2         2 1e+05 236.8000 0.4000000    3.4 2.633333
3       3         2 5e+04 155.2667 0.3333333    5.9 1.300000

一个适用于不平衡情况的聚合解决方案如下。假设任何迭代的第i行是数据集i,并且我们只是在数据集内进行平均。使用聚合很简单。唯一棘手的部分是正确分配行到数据集,使其在不平衡的情况下也能工作。这是通过list(data.set =...)表达式完成的。
> it <- all_results$iteration
> aggregate(all_results, list(data.set = seq_along(it) - match(it, it) + 1), mean)
  data.set iteration lines loadTime    query1 query2   query3
1        1         2 1e+05 158.1000 0.4333333    5.7 3.033333
2        2         2 1e+05 236.8000 0.4000000    3.4 2.633333
3        3         2 5e+04 155.2667 0.3333333    5.9 1.300000

我也在考虑建议同样的事情,但是如果每个“data.frame”的大小不相同,则“+”无法工作。 - Joshua Ulrich
数据框的大小相同,因为发布者指出他发布的代码确实有效,只是他想要更加“优雅”的东西。 - G. Grothendieck
@Gabor,我指的是他问题中的最后一句话。 - Joshua Ulrich
好的。我已经添加了第二个解决方案。可以定义一个加法函数,但在这种情况下,我认为使用聚合更容易。 - G. Grothendieck

1

你是不是有这样的想法?

do.call("rbind", lapply(results, mean))

0

试一下,例如:

with(all_results, tapply(lines, iteration, mean))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接