Подтвердить что ты не робот

Совокупность данных в данном столбце и отображение другого столбца

У меня есть dataframe в 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

Я хотел бы объединить его после столбца Score, используя функцию 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

Любые подсказки?

4b9b3361

Ответ 1

Сначала вы разделите данные с помощью split:

split(z,z$Group)

Чем для каждого фрагмента выберите строку с максимальным счетом:

lapply(split(z,z$Group),function(chunk) chunk[which.max(chunk$Score),])

Наконец, вернемся к data.frame do.call ing rbind:

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

Одна строка, никакие магические заклинания, быстрая, результат имеет хорошие имена =)

Ответ 2

Базовое решение R заключается в объединении вывода aggregate() с шагом merge(). Я считаю интерфейс формул aggregate() немного более полезным, чем стандартный интерфейс, отчасти потому, что имена на выходе более приятные, поэтому я буду использовать это:

Шаг aggregate() -

maxs <- aggregate(Score ~ Group, data = dat, FUN = max)

а шаг merge() - это просто

merge(maxs, dat)

Это дает нам желаемый результат:

R> maxs <- aggregate(Score ~ Group, data = dat, FUN = max)
R> merge(maxs, dat)
  Group Score Info
1     1     3    c
2     2     4    d

Вы могли бы, конечно, вставить это в однострочный (промежуточный шаг был больше для экспозиции):

merge(aggregate(Score ~ Group, data = dat, FUN = max), dat)

Основная причина, по которой я использовал интерфейс формулы, заключается в том, что он возвращает фрейм данных с правильным names для шага слияния; это имена столбцов из исходного набора данных dat. Нам нужно, чтобы на выходе aggregate() были правильные имена, чтобы merge() знал, какие столбцы в исходном и агрегированном кадрах данных совпадают.

Стандартный интерфейс дает нечетные имена, в зависимости от того, как вы его называете:

R> aggregate(dat$Score, list(dat$Group), max)
  Group.1 x
1       1 3
2       2 4
R> with(dat, aggregate(Score, list(Group), max))
  Group.1 x
1       1 3
2       2 4

Мы можем использовать merge() на этих выходах, но нам нужно сделать больше работы, сообщая R, которые соответствуют столбцам.

Ответ 3

Вот решение, использующее пакет plyr.

Следующая строка кода по существу сообщает ddply, чтобы сначала группировать ваши данные по Group, а затем внутри каждой группы возвращает подмножество, в котором показатель равен максимальному значению в этой группе.

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 вернет несколько максимальных строк, если они есть).

Ответ 4

Для этого может использоваться пакет 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

Ответ 5

Поздний ответ, но и с помощью 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 данных для каждой группы, за исключением столбца (ов) группы

Ответ 6

Чтобы добавить к ответам Gavin: до слияния, можно получить агрегат для использования собственных имен, если не использовать интерфейс формулы:

aggregate(data[,"score", drop=F], list(group=data$group), mean) 

Ответ 7

Вот как я 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