Название довольно запутанное (извините), но я попытаюсь объяснить это здесь.
У меня есть набор данных с несколькими именами людей, количеством кофе, который они выпили в определенный день недели, и соответствующим днем недели в трех столбцах.
Например,
В качестве результата мне нужен «день» (столбец 3), когда Том, Мэри и Джон выпили «максимальное» количество кофе. т. е. Том — понедельник, Мэри — пятница, Джон — понедельник в виде таблицы.
x=data.frame(read.csv(file.choose()))
tom=subset(x,x$Name= = "Tom")
tom.max=max(tom)
tom$Day[which.max(tom$Coffees)]
Я мог бы сделать это для одного имени, но изо всех сил пытался использовать цикл, чтобы сделать это для всех имен вместе, чтобы мне не пришлось повторять это для каждого имени в большем наборе данных. Я хочу, чтобы результат выглядел примерно так
Любая помощь будет оценена по достоинству.
Обновлять: Эффективный способ:
dplyr::slice_max(df, Coffees, by=Name)
Name Coffees Day
1 Tom 6 Monday
2 Mary 3 Friday
3 John 5 Monday
#тест:
library(microbenchmark)
mbm = microbenchmark(
tarjae = dplyr::slice_max(df, Coffees, by=Name),
DavOz = df %>%
group_by(Name) %>%
arrange(desc(Coffees), .by_group=TRUE) %>%
slice_head(n=1),
times=50
)
mbm
autoplot(mbm)
Первый ответ:
Вот dplyr
решение:
library(dplyr)
df %>%
slice_max(Coffees, by=Name) %>%
# select(-Coffees)
Name Day
1 Tom Monday
2 Mary Friday
3 John Monday
данные:
df <- data.frame(
Name = c("Tom", "Tom", "Mary", "Tom", "John", "Tom", "Mary", "Tom", "John"),
Coffees = c(2, 1, 3, 4, 5, 6, 1, 2, 3),
Day = c("Monday", "Wednesday", "Friday", "Thursday", "Monday", "Monday", "Tuesday", "Friday", "Saturday")
)
Вот базовый эквивалент R:
max_df <- merge(df, aggregate(Coffees ~ Name, df, max), by = c("Name", "Coffees"))
max_df[, c("Name", "Day")]
Этого можно легко добиться с помощью пакета dplyr
. Обратите внимание, что публикация снимков экрана ваших данных не одобряется — лучше вырезать и вставить реальные цифры (в виде текста) или использовать функцию dput()
.
df <- read.table(sep = "", header=TRUE, text=c("
Name Coffees Day
Tom 2 Monday
Tom 1 Wednesday
Mary 3 Friday
Tom 2 Thursday
John 3 Monday
Tom 4 Monday
Mary 5 Tuesday
Tom 6 Friday
John 1 Saturday
"))
df
#> Name Coffees Day
#> 1 Tom 2 Monday
#> 2 Tom 1 Wednesday
#> 3 Mary 3 Friday
#> 4 Tom 2 Thursday
#> 5 John 3 Monday
#> 6 Tom 4 Monday
#> 7 Mary 5 Tuesday
#> 8 Tom 6 Friday
#> 9 John 1 Saturday
suppressPackageStartupMessages(library(tidyverse))
df %>%
group_by(Name) %>%
arrange(desc(Coffees), .by_group=TRUE) %>%
slice_head(n=1)
#> # A tibble: 3 × 3
#> # Groups: Name [3]
#> Name Coffees Day
#> <chr> <int> <chr>
#> 1 John 3 Monday
#> 2 Mary 5 Tuesday
#> 3 Tom 6 Friday
Created on 2024-05-15 with reprex v2.1.0
Вы можете использовать subset
+ ave
в базе R.
> subset(df, ave(Coffees, Name, FUN = max) == Coffees)
Name Coffees Day
3 Mary 3 Friday
5 John 5 Monday
6 Tom 6 Monday
Мне нравится этот короткий код, краткий и эффективный, +1!