рассчитать среднее по нескольким фреймам данных - PullRequest
6 голосов
/ 19 января 2011

Я хотел бы использовать 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 ]

3 голосов
/ 19 января 2011

Я не понимаю, почему вам нужно разделить all_results на iteration.Вы можете просто использовать aggregate на all_results.Нет необходимости для всех итераций иметь одинаковое количество наблюдений.

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)
3 голосов
/ 19 января 2011

Если я правильно вас понимаю, в данной системе БД на каждой "итерации" (1 ... N) вы загружаете последовательность наборов данных (1,2,3) и выполняете запросы к ним.Кажется, что в конце вы хотите вычислить среднее время для всех итераций, для каждого набора данных .Если это так, вам действительно нужно иметь дополнительный столбец DataSet в таблице 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

Теперь вы можете использовать функцию ddply из пакета plyr, чтобы легко извлечь средние значения для времени загрузки и запроса для каждого набора данных.

> 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

Между прочим, я настоятельно рекомендую вам взглянуть на plyr пакет Хадли Уикхема для богатого набора функций манипулирования данными

1 голос
/ 19 января 2011

Попробуйте:

> 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

Ниже приведено решение aggregate, которое также работает для несбалансированного случая.Предположим, что i-я строка любой итерации предназначена для набора данных i и что мы просто усредняем данные в наборах данных.Использование aggregate прямо вперед.Единственная сложность заключается в правильном назначении строк для наборов данных, чтобы оно работало и в несбалансированном случае.Это делается выражением 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
1 голос
/ 19 января 2011

Вы имели в виду нечто подобное?

do.call("rbind", lapply(results, mean))
0 голосов
/ 19 января 2011

Попробуйте, например,

with(all_results, tapply(lines, iteration, mean))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...