Средний ряд по разным уровням факторов

У меня есть следующий фрейм данных:

df = data.frame(id=c("A","A","A","A","B","B","B","B","C","C","C","C","D","D","D","D"),
                sub=rep(c(1:4),4),
                acc1=runif(16,0,3),
                acc2=runif(16,0,3),
                acc3=runif(16,0,3),
                acc4=runif(16,0,3))

Я хочу получить средние строки для каждого идентификатора, то есть я хочу получить среднее значение acc1, acc2, acc3 и acc4 для каждого уровня A, B, C и D путем усреднения значений для каждого подпункта (4 уровня). для каждого идентификатора), что в конечном итоге дало бы что-то вроде этого (с заменой NA на средства, которые я хочу, конечно):

dfavg = data.frame(id=c("A","B","C","D"),meanacc1=NA,meanacc2=NA,meanacc3=NA,meanacc4=NA)

Заранее спасибо!

4 ответа

Пытаться:

Вы можете использовать любой из специализированных пакетов dplyr или же data.table или используя base R, Потому что у вас есть много столбцов, которые начинаются с acc чтобы получить среднее значение, я выбираю dplyr, Здесь идея состоит в том, чтобы сначала group переменная по id а затем использовать summarise_each чтобы получить mean каждого столбца id это начинается с acc

 library(dplyr)
 df1 <- df %>% 
           group_by(id) %>% 
           summarise_each(funs(mean=mean(., na.rm=TRUE)), starts_with("acc")) %>%
           rename(meanacc1=acc1, meanacc2=acc2, meanacc3=acc3, meanacc4=acc4) #this works but it requires more typing.

я мог бы rename с помощью paste

# colnames(df1)[-1] <- paste0("mean", colnames(df1)[-1]) 

дает результат

 #  id   meanacc1  meanacc2 meanacc3 meanacc4
 #1  A 1.7061929 2.401601 2.057538 1.643627
 #2  B 1.7172095 1.405389 2.132378 1.769410
 #3  C 1.4424233 1.737187 1.998414 1.137112
 #4  D 0.5468509 1.281781 1.790294 1.429353

Или используя data.table

 library(data.table)
 nm1 <- paste0("acc", 1:4) #names of columns to do the `means`
 dt1 <- setDT(df)[, lapply(.SD, mean, na.rm=TRUE), by=id, .SDcols=nm1]

Вот.SD подразумевает Subset of Data.table, .SDcols столбцы, к которым мы применяем mean операция.

 setnames(dt1, 2:5, paste0("mean", nm1)) #change the names of the concerned columns in the result
 dt1

(Это должно быть задано не менее 20 раз.) Функция агрегирования применяет одну и ту же функцию (заданную в качестве третьего аргумента) ко всем столбцам своего первого аргумента в группах, определенных ее вторым аргументом:

aggregate(df[-(1:2)], df[1],mean)

Если вы хотите добавить буквы "означают" к именам столбцов:

names(df2) <- paste0("mean", names(df2)

Если бы вы хотели сделать выбор столбцов автоматически, то сработали бы grep или grepl:

aggregate(df[ grepl("acc", names(df) )], df[1], mean)

Вот несколько других базовых вариантов R:

split + vapply (так как мы знаем vapply упростил бы до матрицы по возможности)

t(vapply(split(df[-c(1, 2)], df[, 1]), colMeans, numeric(4L)))

bydo.call(rbind, ...) чтобы получить окончательную структуру)

do.call(rbind, by(data = df[-c(1, 2)], INDICES = df[[1]], FUN = colMeans))

И то, и другое даст вам что-то вроде этого:

#       acc1     acc2     acc3     acc4
# A 1.337496 2.091926 1.978835 1.799669
# B 1.287303 1.447884 1.297933 1.312325
# C 1.870008 1.145385 1.768011 1.252027
# D 1.682446 1.413716 1.582506 1.274925

Пример данных, использованных здесь был (с set.seedдля воспроизводимости):

set.seed(1)
df = data.frame(id = rep(LETTERS[1:4], 4),
                sub = rep(c(1:4), 4),
                acc1 = runif(16, 0, 3),
                acc2 = runif(16, 0, 3),
                acc3 = runif(16, 0, 3),
                acc4 = runif(16, 0, 3))

Масштабирование до 1М строк позволяет работать достаточно хорошо (хотя, очевидно, не так быстро, как "dplyr" или "data.table").

Вы можете сделать это в самом базовом пакете, используя это:

 a <- list();

 for (i in 1:nlevels(df$id))
 {      
    a[[i]] = colMeans(subset(df, id==levels(df$id)[i])[,c(3,4,5,6)]) ##select columns of df of which you want to compute the means. In your example, 3, 4, 5 and 6 are the columns
 }
 meanDF <- cbind(data.frame(levels(df$id)), data.frame(matrix(unlist(a), nrow=4, ncol=4,  byrow=T)))

colnames(meanDF) = c("id", "meanacc1", "meanacc2", "meanacc3", "meanacc4")
meanDF

id meanacc1 meanacc2  meanacc3  meanacc4
A 1.464635 1.645898 1.7461862 1.026917
B 1.807555 1.097313 1.7135346 1.517892
C 1.350708 1.922609 0.8068907 1.607274
D 1.458911 0.726527 2.4643733 2.141865
Другие вопросы по тегам