1
votes

Comment sélectionner les valeurs les plus élevées en fonction de celles-ci couvrant un certain pourcentage?

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?


0 commentaires

3 Réponses :


3
votes

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>


2 commentaires

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!



0
votes

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 .


0 commentaires

1
votes

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


0 commentaires