#r #split #dataframe #lapply #split-apply-combine
#r #сплит #фрейм данных #лапчатый #разделить-применить-объединить
Вопрос:
Предположим, у меня есть фрейм данных в R, где я хотел бы использовать 2 столбца «factor1» и «factor2» в качестве факторов, и мне нужно вычислить среднее значение для всех остальных столбцов для каждой пары вышеупомянутых факторов. После выполнения приведенного ниже кода в последней строке отображаются следующие предупреждения:
Warning messages:
1: In split.default(seq_along(x), f, drop = drop, ...) :
data length is not a multiple of split variable
…
Почему это происходит и что я должен сделать, чтобы все исправить? Спасибо.
Вот мой код:
# Create data frame
myDataFrame <- data.frame(factor1=c(1,1,1,2,2,2,3,3,3), factor2=c(3,3,3,4,4,4,5,5,5), val1=c(1,2,3,4,5,6,7,8,9), val2=c(9,8,7,6,5,4,3,2,1))
# Split by 2 columns (factors)
splitDataFrame <- split(myDataFrame, list(myDataFrame$factor1, mydataFrame$factor2))
# Calculate mean value for each column per each pair of factors
splitMeanValues <- lapply(splitDataFrame, function(x) apply(x, 2, mean))
# Combine back to reduced table whereas there is only one value (mean) per each pair of factors
MeanValues <- unsplit(splitMeanValues, list(unique(myDataFrame$factor1), unique(mydataFrame$factor2)))
EDIT1: Добавлено создание фрейма данных (см. Выше)
Комментарии:
1. Пожалуйста, предоставьте некоторые примеры данных, чтобы мы могли воспроизвести проблему.
2. @Richard Scriven: Спасибо, только что добавил строку, которая создает фрейм данных, см. Выше в вопросе.
Ответ №1:
Если вам нужно вычислить среднее значение для всех других столбцов, кроме факторов, вы можете использовать синтаксис формулы aggregate()
aggregate(.~factor1 factor2, myDataFrame, FUN=mean)
Это возвращает
factor1 factor2 val1 val2
1 1 3 2 8
2 2 4 5 5
3 3 5 8 2
Ваш split()
метод не сработал, потому что при unsplit
разделении данных у вас должно быть столько же строк, сколько и при разделении данных. Вы уменьшали количество строк для всех групп до одной строки. Кроме того, unsplit
действительно следует использовать с тем же списком факторов, который использовался для выполнения split
, иначе группы могут выйти из строя. Вы могли бы использовать a split
, а затем lapply
некоторую функцию свертывания, а затем rbind
список обратно в один data.frame, если вы действительно хотели, но для простого среднего, aggregate
вероятно, лучше.
Комментарии:
1. Спасибо, ваш метод сработал! Один вопрос, однако, когда я пробовал нерасщепленную, я использовал уникальную функцию в списке, поэтому векторы факторов также должны были быть уменьшены. Почему это не сработало?
2. Основная проблема заключается в том, что ваш splitMeanValues — это не список data.frames, это список именованных векторов.
apply
Функция плохо работает с data.frames, она преобразует входные данные в матрицу и, в конечном счете, в вектор благодаря вашей функции сокращения.
Ответ №2:
Тот же результат может быть получен с summaryBy()
помощью in the doBy
package. Хотя это почти то же aggregate()
самое, что и в этом случае.
> library(doBy)
> summaryBy( . ~ factor1 factor2, data = myDataFrame)
# factor1 factor2 val1.mean val2.mean
# 1 1 3 2 8
# 2 2 4 5 5
# 3 3 5 8 2
Ответ №3:
Вы пробовали aggregate
?
aggregate(myDataFrame$valueColum, myDataFrame$factor1, FUN=mean)
aggregate(myDataFrame$valueColum, myDataFrame$factor2, FUN=mean)
Комментарии:
1. Попробовал: средние значения <- aggregate(myDataFrame, by=list(myDataFrame $factor1, mydataFrame $ factor2), FUN=mean), получил ошибку: аргументы должны иметь одинаковую длину. Все еще ошибка.