I have a data frame (df) that includes the following columns: horse names, ages and speed figures (value). Initially, I plot the data with ggplot geom_boxplot to see the average speed figure value by age.
Now I would like to do the same plot, but this time only include horses that have raced more than three times as a two-year-old, but I'm struggling to figure out how to accomplish this.
I tried to group_by(horse, age), then summarise the nummber of times each horse raced at each age, and finally filter out horses that at 2 years has an n < 4. Unfortunately, I think my logic/approach may be flawed.
Can anyone think of an elegant way of accomplishing this. It seems straightforward, yet I struggle.
library(tidyverse)
#> Warning: package 'ggplot2' was built under R version 4.0.5
library(brew)
#> Warning: package 'brew' was built under R version 4.0.3
df <- tibble(horse=c("a","a","a","a","a","a","a","a","a","a","b","b","b","b","b","b","c","c","c","c","c","c","c","c","c","c","c","c","d","d","d","d","d","d"),
age = c(2,2,2,2,2,3,3,3,4,4,2,2,3,3,3,4,2,2,2,2,2,3,3,3,3,3,4,4,2,3,3,3,3,4),
value = c(20,21,19,23,20,17,16,23,24,14,23,24,18,19,16,19,17,24,19,18,17,15,18,12,12,14,15,11,23,24,14,23,24,18))
df
#> # A tibble: 34 x 3
#> horse age value
#> <chr> <dbl> <dbl>
#> 1 a 2 20
#> 2 a 2 21
#> 3 a 2 19
#> 4 a 2 23
#> 5 a 2 20
#> 6 a 3 17
#> 7 a 3 16
#> 8 a 3 23
#> 9 a 4 24
#> 10 a 4 14
#> # ... with 24 more rows
df %>%
ggplot(aes(x=as.factor(age), y=value, fill=as.factor(age))) +
geom_boxplot(alpha=0.7) +
stat_summary(fun.y=mean, geom="point", shape=20, size=8, color="red", fill="red") +
stat_summary(fun = mean, geom = "text", col = "black", # Add text to plot
vjust = -1.5, aes(label = paste("X:", round(..y.., digits = 1)))) +
theme(legend.position="none") +
scale_fill_brewer(palette="Set1")
#> Warning: `fun.y` is deprecated. Use `fun` instead.
Created on 2021-06-19 by the reprex package (v0.3.0)
If I understood what you are aiming for correctly, the following should work.
Here I assume you want to keep all observations for those horses that races at least 3 races when they were 2 years old, that is, keep also the races before and after as well and not only those observations when they were 2 years old.
library(dplyr)
df <- tibble(horse=c("a","a","a","a","a","a","a","a","a","a","b","b","b","b","b","b","c","c","c","c","c","c","c","c","c","c","c","c","d","d","d","d","d","d"),
age = c(2,2,2,2,2,3,3,3,4,4,2,2,3,3,3,4,2,2,2,2,2,3,3,3,3,3,4,4,2,3,3,3,3,4),
value = c(20,21,19,23,20,17,16,23,24,14,23,24,18,19,16,19,17,24,19,18,17,15,18,12,12,14,15,11,23,24,14,23,24,18))
df %>% group_by(horse, age) %>%
mutate(n_races_by_age = n(),
check_if_keep = if_else(age == 2 & n_races_by_age >= 3, 1, 0)) %>%
ungroup(age) %>%
mutate(
horse_to_keep = max(check_if_keep)
# it is still grouped by horse, so keep all observations of those horses for
# which the above conditions are met.
)
#> # A tibble: 34 x 6
#> # Groups: horse [4]
#> horse age value n_races_by_age check_if_keep horse_to_keep
#> <chr> <dbl> <dbl> <int> <dbl> <dbl>
#> 1 a 2 20 5 1 1
#> 2 a 2 21 5 1 1
#> 3 a 2 19 5 1 1
#> 4 a 2 23 5 1 1
#> 5 a 2 20 5 1 1
#> 6 a 3 17 3 0 1
#> 7 a 3 16 3 0 1
#> 8 a 3 23 3 0 1
#> 9 a 4 24 2 0 1
#> 10 a 4 14 2 0 1
#> # … with 24 more rows
If that is what you mean, then you would only need to add %>% filter(horse_to_keep==1)
to achieve the desired results.
Here are couple of ways to keep the horses in the data that have raced more than 3 times as 2 year old.
filter
-library(dplyr)
df %>%
group_by(horse) %>%
filter(sum(age == 2) > 3) %>%
ungroup
# horse age value
# <chr> <dbl> <dbl>
# 1 a 2 20
# 2 a 2 21
# 3 a 2 19
# 4 a 2 23
# 5 a 2 20
# 6 a 3 17
# 7 a 3 16
# 8 a 3 23
# 9 a 4 24
#10 a 4 14
# … with 12 more rows
df %>%
filter(age == 2) %>%
count(horse) %>%
filter(n > 3) %>%
select(-n) %>%
left_join(df, by = 'horse')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.