2011-01-19 22 views
6

Me gustaría usar R para trazar los resultados de evaluación de rendimiento de distintos sistemas de bases de datos. Para cada sistema cargué los mismos datos y ejecuté las mismas consultas en varias iteraciones.calcule el promedio sobre varias tramas de datos

Los datos para una sola sistemas se ve así:

"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 

Lo que necesito ahora (para el trazado) es un marco de matriz o de datos que contiene el promedio de estas mediciones.

En el momento que estoy haciendo esto:

# 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 

pude poner todo esto en una función y calcular la matriz de la media en un bucle, pero tengo la vaga sensación de que tiene que haber una más elegante solución. ¿Algunas ideas?

¿Qué puedo hacer para los casos en que tengo resultados incompletos, por ejemplo, cuando una iteración tiene menos filas que las otras?

Gracias!

Respuesta

3

Si he entendido bien, en un sistema de base de datos dada, en cada "iteración" (1 ... N) que va a cargar una secuencia de conjuntos de datos (1,2,3) y ejecutar consultas sobre ellas . Parece que al final desea calcular el tiempo promedio en todas las iteraciones, para cada DataSet. Si es así, realmente necesita tener una columna adicional DataSet en su tabla all_results que identifica el conjunto de datos. Podemos añadir esta columna de la siguiente manera:

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 

Ahora puede utilizar la función ddply del paquete plyr para extraer fácilmente los promedios de los tiempos de carga y de consulta para cada conjunto de datos.

> 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 

Por cierto, le recomiendo que mire Hadley Wickham de plyr package para un amplio conjunto de datos en la manipulación funciones

+0

que es de hecho más elegante que para bucles ... gracias por la pista. – behas

+0

¿Qué sucede si quiero incluir la columna "líneas" en el marco de salida de ddply? Podría hacer eso simplemente calculando la media también sobre las líneas; pero esto de alguna manera no tiene sentido ya que los números de línea son valores estáticos; – behas

+0

Veo lo que quiere decir, ¡pero supongo que no hay nada malo en tomar la "media" de un montón de valores idénticos! –

0

intento, por ejemplo,

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

¿Ha tenido algo como esto en mente?

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

Prueba esto:

> 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 

Una solución aggregate que también trabaja para el desequilibrada caso sigue. Supongamos que la i-ésima fila de cualquier iteración es para el conjunto de datos i y que simplemente promediamos dentro de los conjuntos de datos. Usar aggregate es sencillo. La única parte difícil es hacer que la asignación de filas a los conjuntos de datos sea correcta para que también funcione en el caso desequilibrado. Esto se hace mediante la expresión 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 
+0

Estaba pensando en sugerir lo mismo, pero '+' no funciona si cada 'data.frame' no tiene el mismo tamaño. –

+0

Los marcos de datos son del mismo tamaño, ya que el póster indicó que el código que publicó funciona, pero es solo que quiere algo más "elegante". –

+0

@Gabor Me refería a la última oración en su pregunta. –

3

No veo por qué tiene que dividir por all_resultsiteration. Puede simplemente usar aggregate en all_results. No es necesario que todas las iteraciones tengan el mismo número de observaciones.

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

Creo que OP necesita promediar por DataSet como dije en mi respuesta, no por "iteración" (no tiene sentido tomar el promedio de un conjunto de datos que tiene 100000 líneas y una con 50000 líneas). Al menos esa es mi interpretación de lo que realmente quiere hacer. –

+0

... pero la idea de usar 'aggregate' es buena (+1). Solo estaba tratando de usar esto como ejercicio para practicar el uso de 'plyr'. –

Cuestiones relacionadas