Вычислить среднее и стандартное отклонение по группе для нескольких переменных в data.frame
88405 просмотра
5 ответа
Редактировать - Этот вопрос был первоначально озаглавлен «Длинное и широкое изменение формы данных в R»
Я просто изучаю R и пытаюсь найти способы применить его, чтобы помочь другим в моей жизни. В качестве тестового примера я работаю над изменением формы некоторых данных, и у меня возникают проблемы при использовании примеров, которые я нашел в Интернете. То, с чего я начинаю, выглядит так:
ID Obs 1 Obs 2 Obs 3
1 43 48 37
1 27 29 22
1 36 32 40
2 33 38 36
2 29 32 27
2 32 31 35
2 25 28 24
3 45 47 42
3 38 40 36
И то, что я хочу закончить, будет выглядеть так:
ID Obs 1 mean Obs 1 std dev Obs 2 mean Obs 2 std dev
1 x x x x
2 x x x x
3 x x x x
И так далее. В чем я не уверен, так это в том, нужна ли мне дополнительная информация в моих полных данных, или как. Я полагаю, что математическая часть (поиск среднего значения и стандартных отклонений) будет легкой, но мне не удалось найти способ, который, по-видимому, работает, чтобы правильно изменить форму данных, чтобы начать этот процесс.
Большое спасибо за любую помощь.
Автор: user2348358 Источник Размещён: 12.11.2019 09:38Ответы (5)
31 плюса
Это проблема агрегации, а не проблема изменения формы, как изначально предлагался вопрос - мы хотим агрегировать каждый столбец в среднее и стандартное отклонение по идентификатору. Есть много пакетов, которые решают такие проблемы. В основе R это можно сделать aggregate
следующим образом (при условии, DF
что это кадр входных данных):
ag <- aggregate(. ~ ID, DF, function(x) c(mean = mean(x), sd = sd(x)))
Примечание 1: Комментатор указал, что ag
это фрейм данных, для которого некоторые столбцы являются матрицами. Хотя изначально это может показаться странным, на самом деле это упрощает доступ. ag
имеет то же количество столбцов, что и входные данные DF
. Его первый столбец ag[[1]]
- это, ID
а i-й столбец остатка ag[[i+1]]
(или эквивалентно ag[-1][[i]]
) - это матрица статистики для i-го входного столбца наблюдения. Если кто-то хочет получить доступ к j-ой статистике i-го наблюдения, то он ag[[i+1]][, j]
также может быть записан как ag[-1][[i]][, j]
.
С другой стороны, предположим, что есть k
статистические столбцы для каждого наблюдения во входных данных (где k = 2 в вопросе). Затем, если мы сгладим вывод, то для доступа к j-й статистике i-го столбца наблюдения мы должны использовать более сложный ag[[k*(i-1)+j+1]]
или эквивалентный метод ag[-1][[k*(i-1)+j]]
.
Например, сравните простоту первого выражения со вторым:
ag[-1][[2]]
## mean sd
## [1,] 36.333 10.2144
## [2,] 32.250 4.1932
## [3,] 43.500 4.9497
ag_flat <- do.call("data.frame", ag) # flatten
ag_flat[-1][, 2 * (2-1) + 1:2]
## Obs_2.mean Obs_2.sd
## 1 36.333 10.2144
## 2 32.250 4.1932
## 3 43.500 4.9497
Примечание 2: входные данные в воспроизводимой форме:
Lines <- "ID Obs_1 Obs_2 Obs_3
1 43 48 37
1 27 29 22
1 36 32 40
2 33 38 36
2 29 32 27
2 32 31 35
2 25 28 24
3 45 47 42
3 38 40 36"
DF <- read.table(text = Lines, header = TRUE)
Автор: G. Grothendieck
Размещён: 03.05.2013 09:32
18 плюса
Вот, пожалуй, самый простой способ сделать это (с воспроизводимым примером ):
library(plyr)
df <- data.frame(ID=rep(1:3, 3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9))
ddply(df, .(ID), summarize, Obs_1_mean=mean(Obs_1), Obs_1_std_dev=sd(Obs_1),
Obs_2_mean=mean(Obs_2), Obs_2_std_dev=sd(Obs_2))
ID Obs_1_mean Obs_1_std_dev Obs_2_mean Obs_2_std_dev
1 1 -0.13994642 0.8258445 -0.15186380 0.4251405
2 2 1.49982393 0.2282299 0.50816036 0.5812907
3 3 -0.09269806 0.6115075 -0.01943867 1.3348792
РЕДАКТИРОВАТЬ: следующий подход экономит вам много печатать при работе со многими столбцами.
ddply(df, .(ID), colwise(mean))
ID Obs_1 Obs_2 Obs_3
1 1 -0.3748831 0.1787371 1.0749142
2 2 -1.0363973 0.0157575 -0.8826969
3 3 1.0721708 -1.1339571 -0.5983944
ddply(df, .(ID), colwise(sd))
ID Obs_1 Obs_2 Obs_3
1 1 0.8732498 0.4853133 0.5945867
2 2 0.2978193 1.0451626 0.5235572
3 3 0.4796820 0.7563216 1.4404602
Автор: Carson
Размещён: 03.05.2013 09:16
16 плюса
Есть несколько разных способов сделать это. reshape2
это полезный пакет Лично мне нравится использоватьdata.table
Ниже приведен пошаговый
Если myDF
это ваш data.frame
:
library(data.table)
DT <- data.table(myDF)
DT
# this will get you your mean and SD's for each column
DT[, sapply(.SD, function(x) list(mean=mean(x), sd=sd(x)))]
# adding a `by` argument will give you the groupings
DT[, sapply(.SD, function(x) list(mean=mean(x), sd=sd(x))), by=ID]
# If you would like to round the values:
DT[, sapply(.SD, function(x) list(mean=round(mean(x), 3), sd=round(sd(x), 3))), by=ID]
# If we want to add names to the columns
wide <- setnames(DT[, sapply(.SD, function(x) list(mean=round(mean(x), 3), sd=round(sd(x), 3))), by=ID], c("ID", sapply(names(DT)[-1], paste0, c(".men", ".SD"))))
wide
ID Obs.1.men Obs.1.SD Obs.2.men Obs.2.SD Obs.3.men Obs.3.SD
1: 1 35.333 8.021 36.333 10.214 33.0 9.644
2: 2 29.750 3.594 32.250 4.193 30.5 5.916
3: 3 41.500 4.950 43.500 4.950 39.0 4.243
Кроме того, это может или не может быть полезным
> DT[, sapply(.SD, summary), .SDcols=names(DT)[-1]]
Obs.1 Obs.2 Obs.3
Min. 25.00 28.00 22.00
1st Qu. 29.00 31.00 27.00
Median 33.00 32.00 36.00
Mean 34.22 36.11 33.22
3rd Qu. 38.00 40.00 37.00
Max. 45.00 48.00 42.00
Автор: Ricardo Saporta
Размещён: 03.05.2013 09:08
9 плюса
Я добавляю dplyr
решение.
set.seed(1)
df <- data.frame(ID=rep(1:3, 3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9))
library(dplyr)
df %>% group_by(ID) %>% summarise_each(funs(mean, sd))
# ID Obs_1_mean Obs_2_mean Obs_3_mean Obs_1_sd Obs_2_sd Obs_3_sd
# (int) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl)
# 1 1 0.4854187 -0.3238542 0.7410611 1.1108687 0.2885969 0.1067961
# 2 2 0.4171586 -0.2397030 0.2041125 0.2875411 1.8732682 0.3438338
# 3 3 -0.3601052 0.8195368 -0.4087233 0.8105370 0.3829833 1.4705692
Автор: Joe
Размещён: 14.04.2016 09:13
8 плюса
Вот еще один подход к data.table
ответам, используя данные @ Carson, который немного более читабелен (а также немного быстрее, благодаря использованию lapply
вместо sapply
):
library(data.table)
set.seed(1)
dt = data.table(ID=c(1:3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9))
dt[, c(mean = lapply(.SD, mean), sd = lapply(.SD, sd)), by = ID]
# ID mean.Obs_1 mean.Obs_2 mean.Obs_3 sd.Obs_1 sd.Obs_2 sd.Obs_3
#1: 1 0.4854187 -0.3238542 0.7410611 1.1108687 0.2885969 0.1067961
#2: 2 0.4171586 -0.2397030 0.2041125 0.2875411 1.8732682 0.3438338
#3: 3 -0.3601052 0.8195368 -0.4087233 0.8105370 0.3829833 1.4705692
Автор: eddi
Размещён: 03.05.2013 09:31
Вопросы из категории :
- r Как получить доступ к последнему значению в векторе?
- r Пакеты оптимизации для R
- r Есть ли у R такие операторские операции, как Perl qw ()?
- r Библиотека / инструмент для рисования тройных / треугольных графиков
- r Участки без заголовков / надписей в R
- aggregate Как использовать GROUP BY для объединения строк в MySQL?
- aggregate Как проверить существующие агрегатные функции в Postgres?
- aggregate Группировать по нескольким столбцам
- aggregate Я нарушаю свои совокупные границы?
- aggregate Вопрос эффективности Linq - foreach против агрегатов
- reshape How do I resize a matrix in MATLAB?
- reshape Преобразование данных из многих строк во многие столбцы
- reshape Изменение формы data.frame из широкого в длинный формат
- reshape Измените 3d матрицу на 2d матрицу
- reshape Как изменить данные из длинного в широкий формат
- reshape2 Более быстрые способы вычисления частот и приведение от длинного к широкому
- reshape2 melt / reshape in excel using VBA?
- reshape2 Преобразование нескольких наборов столбцов измерений (широкий формат) в отдельные столбцы (длинный формат)
- reshape2 Вычислить среднее и стандартное отклонение по группе для нескольких переменных в data.frame
- reshape2 R изменить вектор в несколько столбцов