简体   繁体   中英

dplyr sample_n by one variable through another one

I have a data frame with a "grouping" variable season and another variable year which is repeated for each month.

df <- data.frame(month = as.character(sapply(month.name,function(x)rep(x,4))),
                  season = c(rep("winter",8),rep("spring",12),rep("summer",12),rep("autumn",12),rep("winter",4)), 
                  year = rep(2021:2024,12))

I would like to use dplyr::sample_n or something similar to choose 2 months in the data frame for each season and keep the same months for all the years, for example:

     month        season     year
1     January     winter     2021
2     January     winter     2022
3     January     winter     2023
4     January     winter     2024
5     February    winter     2021
6     February    winter     2022
7     February    winter     2023
8     February    winter     2024
9     March       spring     2021
10    March       spring     2022
11    March       spring     2023
12    March       spring     2024
13    May         spring     2021
14    May         spring     2022
15    May         spring     2023
16    May         spring     2024
17    June        summer     2021
18    June        summer     2022
19    June        summer     2023
20    June        summer     2024
21    July        summer     2021
22    July        summer     2022
23    July        summer     2023
24    July        summer     2024
25    October     autumn     2021
26    October     autumn     2022
27    October     autumn     2023
28    October     autumn     2024
29    November    autumn     2021
30    November    autumn     2022
31    November    autumn     2023
32    November    autumn     2024

I cannot make df %>% group_by(season,year) %>% sample_n(2) since it chooses different months for each year.

Thanks!

We can randomly sample 2 values from month and filter them by group.

library(dplyr)

df %>%
  group_by(season) %>%
  filter(month %in% sample(unique(month),2))


#   month    season  year
#   <chr>    <chr>  <int>
# 1 January  winter  2021
# 2 January  winter  2022
# 3 January  winter  2023
# 4 January  winter  2024
# 5 February winter  2021
# 6 February winter  2022
# 7 February winter  2023
# 8 February winter  2024
# 9 March    spring  2021
#10 March    spring  2022
# … with 22 more rows

If for certain groups there are less than 2 unique values we can select min imum between 2 and unique values in the group to sample .

df %>%
  group_by(season) %>%
  filter(month %in% sample(unique(month),min(2, n_distinct(month))))

Using the same logic with base R, we can use ave

df[as.logical(with(df, ave(month, season, 
             FUN = function(x) x %in% sample(unique(x),2)))), ]

An option using slice

library(dplyr)
df %>% 
   group_by(season) %>% 
    slice(which(!is.na(match(month, sample(unique(month), 2)))))
# A tibble: 32 x 3
# Groups:   season [4]
#   month    season  year
#   <fct>    <fct>  <int>
# 1 October  autumn  2021
# 2 October  autumn  2022
# 3 October  autumn  2023
# 4 October  autumn  2024
# 5 November autumn  2021
# 6 November autumn  2022
# 7 November autumn  2023
# 8 November autumn  2024
# 9 April    spring  2021
#10 April    spring  2022
# … with 22 more rows

Or using base R

by(df, df$season, FUN = function(x) subset(x, month %in% sample(unique(month), 2 )))

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM