Агрегатные таблицы данных по заданному столбцу и вывести еще одну колонку
у меня есть фрейм данных в R следующего вида:
> head(data)
Group Score Info
1 1 1 a
2 1 2 b
3 1 3 c
4 2 4 d
5 2 3 e
6 2 1 f
Я хотел бы объединить их после С помощью max
функции
> aggregate(data$Score, list(data$Group), max)
Group.1 x
1 1 3
2 2 4
но я также хотел бы, чтобы отобразить Info
столбец, связанный с максимальным значением Score
столбец для каждой группы. Я понятия не имею, как это делать. Мой желаемый результат будет:
Group.1 x y
1 1 3 c
2 2 4 d
любой намек?
8 ответов:
во-первых, вы разделяете данные с помощью
split
:split(z,z$Group)
чем, для каждого куска, выберите строку с максимальным счетом:
lapply(split(z,z$Group),function(chunk) chunk[which.max(chunk$Score),])
наконец уменьшить обратно к данным.кадр
do.call
ingrbind
:do.call(rbind,lapply(split(z,z$Group),function(chunk) chunk[which.max(chunk$Score),]))
результат:
Group Score Info 1 1 3 c 2 2 4 d
одна строка, никаких магических заклинаний, быстро, результат имеет хорошие имена =)
вот решение с помощью
plyr
пакета.следующая строка кода по существу говорит
ddply
чтобы сначала сгруппировать данные по группам, а затем в каждой группе возвращает подмножество, где оценка равна максимальной оценке в этой группе.library(plyr) ddply(data, .(Group), function(x)x[x$Score==max(x$Score), ]) Group Score Info 1 1 3 c 2 2 4 d
и, как указывает @SachaEpskamp, это можно еще больше упростить:
ddply(df, .(Group), function(x)x[which.max(x$Score), ])
(которая также имеет то преимущество, что
which.max
вернет несколько максимальных строк, если таковые имеются).
The
plyr
пакет может быть использован для этого. С помощьюddply()
функция вы можете разделить фрейм данных на один или несколько столбцов и применить функцию и вернуть фрейм данных, а затем с помощьюsummarize()
функция вы можете использовать столбцы разделенного фрейма данных в качестве переменных, чтобы создать новый фрейм данных/;dat <- read.table(textConnection('Group Score Info 1 1 1 a 2 1 2 b 3 1 3 c 4 2 4 d 5 2 3 e 6 2 1 f')) library("plyr") ddply(dat,.(Group),summarize, Max = max(Score), Info = Info[which.max(Score)]) Group Max Info 1 1 3 c 2 2 4 d
поздний ответ, но и подход, используя
data.table
library(data.table) DT <- data.table(dat) DT[, .SD[which.max(Score),], by = Group]
или, если это возможно, чтобы иметь более одного одинаково высокий балл
DT[, .SD[which(Score == max(Score)),], by = Group]
отметить, что (с
?data.table
.SD
- это данные.таблица, содержащая подмножество данных x для каждой группы, исключая столбец (ы) группы
чтобы добавить к ответу Гэвина: до слияния можно заставить aggregate использовать собственные имена, когда не используется интерфейс формулы:
aggregate(data[,"score", drop=F], list(group=data$group), mean)
вот как я
base
Я думаю о проблеме.my.df <- data.frame(group = rep(c(1,2), each = 3), score = runif(6), info = letters[1:6]) my.agg <- with(my.df, aggregate(score, list(group), max)) my.df.split <- with(my.df, split(x = my.df, f = group)) my.agg$info <- unlist(lapply(my.df.split, FUN = function(x) { x[which(x$score == max(x$score)), "info"] })) > my.agg Group.1 x info 1 1 0.9344336 a 2 2 0.7699763 e
у меня нет достаточно высокой репутации, чтобы прокомментировать ответ Гэвина Симпсона, но я хотел предупредить, что, похоже, существует разница в обработке по умолчанию пропущенных значений между стандартным синтаксисом и синтаксисом формулы для
aggregate
.#Create some data with missing values a<-data.frame(day=rep(1,5),hour=c(1,2,3,3,4),val=c(1,NA,3,NA,5)) day hour val 1 1 1 1 2 1 2 NA 3 1 3 3 4 1 3 NA 5 1 4 5 #Standard syntax aggregate(a$val,by=list(day=a$day,hour=a$hour),mean,na.rm=T) day hour x 1 1 1 1 2 1 2 NaN 3 1 3 3 4 1 4 5 #Formula syntax. Note the index for hour 2 has been silently dropped. aggregate(val ~ hour + day,data=a,mean,na.rm=T) hour day val 1 1 1 1 2 3 1 3 3 4 1 5