4
votes

Résumer? Compter les occurrences dans la colonne en fonction d'une autre colonne

Je pense que cela peut avoir une solution simple mais j'ai du mal à décrire ce que je dois faire (et donc ce que je dois rechercher). Je pense que j'ai besoin de la fonction résumé . La sortie de mon objectif est tout en bas.

J'essaie de compter les occurrences d'une valeur entre chaque valeur unique dans une autre colonne. Voici un exemple df qui, espérons-le, illustre ce que je dois faire.

  name  count medianDate life      wins  chicken  beef  fish
1 dinah     2 1999-01-13  25 days    19        1     1     0
2 lucy      4 1999-03-29  75 days    69        1     1     2
3 sora      9 1999-09-08 200 days   101        3     3     3

Entre autres, j'essaie de résumer (additionner) les types des repas que chaque nom a pris en utilisant ces données.

df %>% 
  group_by(name) %>% 
  summarise(count=n(),
            medianDate=median(date),
            life=(max(date)-min(date)),
            wins=sum(num.wins))

# A tibble: 3 x 5
  name  count medianDate life      wins
  <chr> <int> <date>     <time>   <int>
1 dinah     2 1999-01-13  25 days    19
2 lucy      4 1999-03-29  75 days    69
3 sora      9 1999-09-08 200 days   101

J'ai fait des progrès avec d'autres calculs qui m'intéressent, ci-dessous:

df
# A tibble: 15 x 4
   name  meal    date       num.wins
   <chr> <chr>   <date>        <int>
 1 dinah chicken 1999-01-01        8
 2 dinah beef    1999-01-26       11
 3 lucy  fish    1999-02-20       16
 4 lucy  chicken 1999-03-17       25
 5 lucy  beef    1999-04-11        5
 6 lucy  fish    1999-05-06       23
 7 sora  chicken 1999-05-31       27
 8 sora  beef    1999-06-25       15
 9 sora  fish    1999-07-20       14
10 sora  chicken 1999-08-14        1
11 sora  beef    1999-09-08        4
12 sora  fish    1999-10-03        3
13 sora  chicken 1999-10-28       13
14 sora  beef    1999-11-22        6
15 sora  fish    1999-12-17       18


1 commentaires

Je suppose que vous pouvez utiliser spread du package tidyr et fusionner / joindre avec votre table résumée.


3 Réponses :


4
votes

Je ne suis pas tout à fait sûr de savoir pourquoi j'obtiens le formatage funky pour life , mais je pense que cela répond à votre besoin de compter les types de repas.

df %>% 
  group_by(name) %>% 
  summarise(count=n(),
            medianDate=median(date),
            life=(max(date)-min(date)),
            wins=sum(num.wins),
            chicken = sum(meal == "chicken"),
            beef = sum(meal == "beef"),
            fish = sum(meal == "fish"))

# A tibble: 3 x 8
  name  count medianDate life        wins chicken  beef  fish
  <chr> <int> <date>     <time>     <int>   <int> <int> <int>
1 dinah     2 1999-01-13 " 25 days"    19       1     1     0
2 lucy      4 1999-03-29 " 75 days"    69       1     1     2
3 sora      9 1999-09-08 200 days     101       3     3     3


1 commentaires

merci cette réponse est utile et beaucoup plus simple que je ne le pensais. J'ai vérifié la réponse de Gregor car dans mon cas j'ai beaucoup de "nourritures" et sa méthode ne m'oblige pas à les lister manuellement. Merci encore



4
votes

Une option consiste à utiliser table dans summary comme colonne list , unnest puis étendre au format "large"

library(tidyverse)
df %>% 
  group_by(name) %>%
  summarise(count=n(),
             medianDate=median(date),
             life=(max(date)-min(date)),
             wins=sum(num.wins),
             n = list(enframe(table(meal))) ) %>%
  unnest %>%
  spread(name1, value, fill = 0)
# A tibble: 3 x 8
#  name  count medianDate life      wins  beef chicken  fish
#  <chr> <int> <date>     <time>   <int> <dbl>   <dbl> <dbl>
#1 dinah     2 1999-01-13  25 days    19     1       1     0
#2 lucy      4 1999-03-29  75 days    69     1       1     2
#3 sora      9 1999-09-08 200 days   101     3       3     3


1 commentaires

C'est aussi génial, si je n'avais pas utilisé la réponse cochée, j'aurais utilisé celle-ci. Je vous remercie



5
votes

Bien que plus ancien, et peut-être sur un chemin de dépréciation, reshape2 :: dcast le fait bien:

df %>% 
  group_by(name) %>% 
  summarise(count=n(),
            medianDate=median(date),
            life=(max(date)-min(date)),
            wins=sum(num.wins)) %>%
  left_join(reshape2::dcast(df, name ~ meal))
# # A tibble: 3 x 8
#   name  count medianDate life      wins  beef chicken  fish
#   <chr> <int> <date>     <time>   <int> <int>   <int> <int>
# 1 dinah     2 1999-01-13  25 days    19     1       1     0
# 2 lucy      4 1999-03-29  75 days    69     1       1     2
# 3 sora      9 1999-09-08 200 days   101     3       3     3

Vous pouvez comprendre la formule sous forme de lignes ~ colonnes . Par défaut, il agrégera les valeurs dans les colonnes en utilisant la fonction length --- qui donne exactement ce que vous voulez, le nombre de chacun.

Ceci peut être facilement joint à vos données récapitulatives:

reshape2::dcast(df, name ~ meal)
#    name beef chicken fish
# 1 dinah    1       1    0
# 2  lucy    1       1    2
# 3  sora    3       3    3


0 commentaires