Je souhaite choisir les meilleurs pays en fonction de la part de la production totale qu'ils couvrent. Je veux que les pays que j'ai filtrés couvrent au moins 50% de la production totale.
J'ai ces données:
# A tibble: 4 x 6 # Groups: item [4] iso3_code country item value share cumulative_share <chr> <chr> <chr> <dbl> <dbl> <dbl> 1 USA USA Maize 392450840 0.422 0.422 2 IDN Indonesia Oil palm fruit 115267491 0.451 0.451 3 USA USA Soybeans 123664230 0.367 0.367 4 BRA Brazil Sugar cane 746828157 0.468 0.468
Ce que j'ai fait, c'est de calculer au sein du groupe «poste», la part pour chaque pays et la part cumulée. Ensuite, je filtre au sein de chaque groupe qui a au plus 0,5 en part cumulée.
production %>% group_by(item) %>% mutate(share = value / sum(value), cumulative_share = cumsum(share)) %>% filter(cumulative_share <= 0.5)
Ce qui me donne:
production = structure(list(iso3_code = c("USA", "CHN", "BRA", "ARG", "UKR", "IDN", "IND", "MEX", "ROU", "CAN", "IDN", "MYS", "THA", "NGA", "COL", "ECU", "CMR", "GHA", "PNG", "HND", "USA", "BRA", "ARG", "CHN", "IND", "PRY", "CAN", "UKR", "RUS", "BOL", "BRA", "IND", "CHN", "THA", "PAK", "MEX", "COL", "GTM", "AUS", "USA"), country = c("USA", "China", "Brazil", "Argentina", "Ukraine", "Indonesia", "India", "Mexico", "Romania", "Canada", "Indonesia", "Malaysia", "Thailand", "Nigeria", "Colombia", "Ecuador", "Cameroon", "Ghana", "Papua New Guinea", "Honduras", "USA", "Brazil", "Argentina", "China", "India", "Paraguay", "Canada", "Ukraine", "Russia", "Bolivia", "Brazil", "India", "China", "Thailand", "Pakistan", "Mexico", "Colombia", "Guatemala", "Australia", "USA"), item = c("Maize", "Maize", "Maize", "Maize", "Maize", "Maize", "Maize", "Maize", "Maize", "Maize", "Oil palm fruit", "Oil palm fruit", "Oil palm fruit", "Oil palm fruit", "Oil palm fruit", "Oil palm fruit", "Oil palm fruit", "Oil palm fruit", "Oil palm fruit", "Oil palm fruit", "Soybeans", "Soybeans", "Soybeans", "Soybeans", "Soybeans", "Soybeans", "Soybeans", "Soybeans", "Soybeans", "Soybeans", "Sugar cane", "Sugar cane", "Sugar cane", "Sugar cane", "Sugar cane", "Sugar cane", "Sugar cane", "Sugar cane", "Sugar cane", "Sugar cane" ), value = c(392450840, 257173900, 82288298, 43462323, 35801050, 30253938, 27820000, 27169977, 18663939, 13884800, 115267491, 98419400, 15400000, 7850000, 5878504, 2785756, 2641118, 2604387, 2496325, 2493910, 123664230, 117887672, 37787927, 14189217, 13786000, 11045971, 7266600, 4460770, 4026850, 2942131, 746828157, 376900000, 108097100, 104360867, 67173975, 56841523, 36276860, 35568207, 33506830, 31335984)), class = c("tbl_df", "tbl", "data.frame" ), row.names = c(NA, -40L), spec = structure(list(cols = list( iso3_code = structure(list(), class = c("collector_character", "collector")), country = structure(list(), class = c("collector_character", "collector")), item = structure(list(), class = c("collector_character", "collector")), value = structure(list(), class = c("collector_double", "collector")), share = structure(list(), class = c("collector_double", "collector")), cumulative_share = structure(list(), class = c("collector_double", "collector"))), default = structure(list(), class = c("collector_guess", "collector")), skip = 1), class = "col_spec"))
Mais Je souhaite dans chaque groupe "élément" sélectionner les principaux pays qui couvrent au moins 50% du total de la "valeur" au sein de ce groupe. Donc, pour le maïs, je veux sélectionner les États-Unis et la Chine (puisqu'ils couvrent 0,422 + 0,277 = 0,699> 0,5).
Des idées pour résoudre ce problème?
3 Réponses :
Utilisez lag
pour tout sélectionner jusqu'à et y compris la première instance où votre condition est fausse. L'utilisation de default = TRUE
garantit que tout est décalé et qu'un TRUE
est ajouté au début, de sorte que la première observation soit également incluse.
library(tidyverse) production %>% group_by(item) %>% arrange(desc(value)) %>% mutate(share = value / sum(value), cumulative_share = cumsum(share)) %>% filter(lag(cumulative_share <= 0.5, default = TRUE)) %>% ungroup() # iso3_code country item value share cumulative_share # <chr> <chr> <chr> <dbl> <dbl> <dbl> # 1 BRA Brazil Sugar cane 746828157 0.468 0.468 # 2 USA USA Maize 392450840 0.422 0.422 # 3 IND India Sugar cane 376900000 0.236 0.704 # 4 CHN China Maize 257173900 0.277 0.699 # 5 USA USA Soybeans 123664230 0.367 0.367 # 6 BRA Brazil Soybeans 117887672 0.350 0.717 # 7 IDN Indonesia Oil palm fruit 115267491 0.451 0.451 # 8 MYS Malaysia Oil palm fruit 98419400 0.385 0.835
p>
arrange (desc (valeur), .by_group = T)
est mieux.
Cela fonctionne parfaitement! Avec l'ajout de Darren Tsai pour ajouter le regroupement car il montre également chaque pays au sein de chaque groupe organisé et non la liste entière comme organisé. Merci à tous les deux!
Avez-vous besoin de quelque chose comme ça?
library(dplyr) production %>% group_by(item) %>% mutate(share = value / sum(value), cumulative_share = cumsum(share)) %>% ungroup %>% slice(seq_len(which.max(cumulative_share >= 0.5))) # A tibble: 2 x 6 # iso3_code country item value share cumulative_share # <chr> <chr> <chr> <dbl> <dbl> <dbl> #1 USA USA Maize 392450840 0.422 0.422 #2 CHN China Maize 257173900 0.277 0.699
Ceci sélectionne les lignes jusqu'à ce que cumulative_share
ne croise pas 0.5
.
cumsum ()
un vecteur logique pour trouver le premier cumulative_share
supérieur ou égal à 0,5.
library(dplyr) production %>% group_by(item) %>% mutate(share = value / sum(value), cumulative_share = cumsum(share)) %>% filter(cumsum(cumulative_share >= 0.5) <= 1) %>% ungroup() # # A tibble: 8 x 6 # iso3_code country item value share cumulative_share # <chr> <chr> <chr> <dbl> <dbl> <dbl> # 1 USA USA Maize 392450840 0.422 0.422 # 2 CHN China Maize 257173900 0.277 0.699 # 3 IDN Indonesia Oil palm fruit 115267491 0.451 0.451 # 4 MYS Malaysia Oil palm fruit 98419400 0.385 0.835 # 5 USA USA Soybeans 123664230 0.367 0.367 # 6 BRA Brazil Soybeans 117887672 0.350 0.717 # 7 BRA Brazil Sugar cane 746828157 0.468 0.468 # 8 IND India Sugar cane 376900000 0.236 0.704