Совокупность по уровням факторов, сохранение других переменных в результирующем кадре данных

Я пытаюсь вычислить минимальные значения числового столбца для каждого уровня фактора, сохраняя при этом значения другого фактора в результирующем кадре данных.

# dummy data
dat <- data.frame(
    code = c("HH11", "HH45", "JL03", "JL03", "JL03", "HH11"), 
    index = c("023434", "3377477", "3388595", "3377477", "1177777", "023434"), 
    value = c(24.1, 37.2, 78.9, 45.9, 20.0, 34.6)
    )

Я хочу получить минимум value для каждого уровня code, сохраняя index в результирующем кадре данных.

# result I want:
#   code value    index
# 1 HH11  24.1   023434
# 2 HH45  37.2  3377477
# 3 JL03  20.0  1177777


# ddply attempt
library(plyr)
ddply(dat, ~ code, summarise, val = min(value))
#   code   val
# 1 HH11  24.1
# 2 HH45  37.2
# 3 JL03  20.0


# base R attempt
aggregate(value ~ code, dat, min)
#   code value
# 1 HH11  24.1
# 2 HH45  37.2
# 3 JL03  20.0

Ответ 1

Вам нужно использовать merge по результату aggregate и оригиналу data.frame

merge(aggregate(value ~ code, dat, min), dat, by = c("code", "value"))
##   code value   index
## 1 HH11  24.1  023434
## 2 HH45  37.2 3377477
## 3 JL03  20.0 1177777

Ответ 2

Просто чтобы показать, что всегда есть несколько способов скинуть кошку:

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

dat[which(ave(dat$value,dat$code,FUN=function(x) x==min(x))==1),]

#  code   index value
#1 HH11  023434  24.1
#2 HH45 3377477  37.2
#5 JL03 1177777  20.0

Этот метод также имеет потенциальную выгоду для возвращения нескольких строк в группу code в экземпляре нескольких значений, являющихся минимальными.

И другой метод с использованием by:

do.call(rbind,
  by(dat, dat$code, function(x) cbind(x[1,c("code","index")],value=min(x$value)))
)
#      code   index value
# HH11 HH11  023434  24.1
# HH45 HH45 3377477  37.2
# JL03 JL03 3388595  20.0

Ответ 3

С пакетами dplyr и data.table вы можете сделать следующее. Вы можете получить индекс для строки, имеющей минимальное значение для каждой группы. Вы можете использовать это в slice(), если используете dplyr. Вы можете достичь того же подмножества, используя .SD, если используете data.table.

library(dplyr)
library(data.table)

dat %>%
group_by(code) %>%
slice(which.min(value))

#    code   index value
#  <fctr>  <fctr> <dbl>
#1   HH11  023434  24.1
#2   HH45 3377477  37.2
#3   JL03 1177777  20.0

setDT(dat)[, .SD[which.min(value)], by = code]

#   code   index value
#1: HH11  023434  24.1
#2: HH45 3377477  37.2
#3: JL03 1177777  20.0

Ответ 4

Хорошо, еще несколько минут поиска меня достали бы... этот ответ, похоже, делает трюк:

merge (dat, aggregate (value ~ code, dat, min))

Ответ 5

Если вы добавили в индексную переменную, которая бы это сделала.

library(plyr)

# ddply
ddply(dat, .(code,index), summarise, val = min(value))

# base R
aggregate(value ~ code + index, dat, min)