У меня есть data.frame, который похож на это
> head(df)
Memory Memory Memory Memory Memory Naive Naive
10472501 6.075714 5.898929 6.644946 6.023901 6.332126 8.087944 7.520194
10509163 6.168941 6.495393 5.951124 6.052527 6.404401 7.152890 8.335509
10496091 10.125575 9.966211 10.075613 10.310952 10.090649 11.803949 11.274480
10427035 6.644921 6.658567 6.569745 6.499243 6.990852 8.010784 7.798154
10503695 8.379494 8.153917 8.246484 8.390747 8.346748 9.540236 9.091740
10451763 10.986717 11.233819 10.643245 10.230697 10.541396 12.248487 11.823138
и я хотел бы найти средний из Memory
столбцы и средний из Naive
столбцы. aggregate
функция агрегировала строки. Это data.frame
мог потенциально иметь большое количество строк, и следовательно транспонирующий затем применение aggregate
colnames
из оригинала data.frame
кажется мне плохо и является обычно раздражающим:
> head(t(aggregate(t(df),list(colnames(df)), mean)))
[,1] [,2]
Group.1 "Memory" "Naive"
10472501 "6.195123" "8.125439"
10509163 "6.214477" "7.733625"
10496091 "10.11380" "11.55348"
10427035 "6.672665" "8.266854"
10503695 "8.303478" "9.340436"
Какова ослепляюще очевидная вещь, которую я пропускаю?
Я большой сторонник переформатирования данных так, чтобы они были в "длинном" формате. Полезность длинного формата особенно очевидна, когда речь идет о проблемах, подобных этой. К счастью, с помощью пакета reshape
достаточно легко переформатировать такие данные практически в любой формат.
Если я правильно понял ваш вопрос, вам нужно среднее значение Memory
и Naive
для каждой строки. По какой-то причине нам нужно сделать имена столбцов уникальными для reshape::melt()
.
colnames(df) <- paste(colnames(df), 1:ncol(df), sep = "_")
Тогда вам придется создать колонку ID
. Вы можете сделать это
df$ID <- 1:nrow(df)
или, если эти имена имеют смысл
df$ID <- rownames(df)
Теперь, с помощью пакета reshape
library(reshape)
df.m <- melt(df, id = "ID")
df.m <- cbind(df.m, colsplit(df.m$variable, split = "_", names = c("Measure", "N")))
df.agg <- cast(df.m, ID ~ Measure, fun = mean)
df.agg
должен выглядеть как желаемый фрагмент вывода.
Или, если вам нужны только общие средние по всем строкам, подойдет предложение Зака. Что-то вроде
m <- colMeans(df)
tapply(m, colnames(df), mean)
Вы можете получить тот же результат, но в формате dataframe с
cast(df.m, .~variable, fun = mean)
А что насчет чего-то вроде
l <-lapply(unique(colnames(df)), function(x) rowMeans(df[,colnames(df) == x]))
df <- do.call(cbind.data.frame, l)
Чтобы прояснить ответ Джонатана Чанга ... слепо очевидная вещь, которую вам не хватает, - это то, что вы можете просто выбрать столбцы и выполнить команду rowMeans. Это даст вектор средних для каждой строки. Его команда получает средние строки для каждой группы уникальных имен столбцов, и это именно то, что я собирался написать. С вашими образцами данных результатом его команды являются два списка.
rowMeans также работает очень быстро.
Чтобы разбить его на части, получить только средства всех столбцов вашей памяти - это всего лишь
rowMeans(df[,colnames(df) == 'Memory']) #or from you example, rowMeans(df[,1:5])
Это простейший полный правильный ответ, проголосуйте за него и отметьте его правильным, если он вам нравится.
(Кстати, мне также понравилась рекомендация Джо хранить в целом длинные данные.)
Я думаю, вы загрузили свои данные без header = TRUE
, и у вас есть матрица факторов, и поэтому ваша в целом хорошая идея терпит неудачу.