Comprensión de la tubería dplyr y función de resumen

Aug 20 2020

Estoy buscando ayuda para comprender la tubería y resumir funciones usando dplyr. Siento que mi codificación es un poco detallada y podría simplificarse. Entonces, hay un par de preguntas aquí porque sé que me faltan algunos conceptos, pero no estoy muy seguro de dónde está esa falta de conocimiento. Incluí mi código completo en la parte inferior. Gracias de antemano ya que esta es una pregunta un poco más grande.

1a. A partir de los datos de ejemplo a continuación y usando dplyr, ¿hay alguna manera de calcular los juegos (fechas) por equipo sin usar una tabla intermedia?

1b. He incluido mi forma original de calcular n_games que no funcionó. ¿Por qué?

set.seed(123)
shot_df_ex <- tibble(Team_Name = sample(LETTERS[1:5],250, replace = TRUE),
                     Date = sample(as.Date(c("2019-08-01",
                                             "2019-09-01",
                                             "2018-08-01",
                                             "2018-09-01",
                                             "2017-08-01",
                                             "2017-09-01")), 
                                   size = 250, replace = TRUE),
                     Type = sample(c("shot","goal"), size = 250, 
                                   replace = TRUE, prob = c(0.9,0.1))
)

# count shots per team per game(date)
n_shots_per_game <- shot_df_ex %>% 
  count(Team_Name,Date)

n_shots_per_game

# count games (dates) per team [ISSUES!!!]
# is there a way to do this piping from the shot_df_ex tibble instead of 
#  using an intermediate tibble?

# count number of games using the tibble created above [DOES NOT WORK--WHY?]
n_games <- n_shots_per_game %>% 
  count(Team_Name)

n_games #what is this counting? It should be 6 for each.

# this works, but isn't count() just a quicker way to run
#  group_by() %>% summarise()? 
n_games <- n_shots_per_game %>% 
  group_by(Team_Name) %>% 
  summarise(N_Games=n())

n_games
  1. A continuación se muestra mi proceso de creación de una tabla de resumen. Entiendo que la canalización está destinada a eliminar la creación de algunas variables / tablas intermedias. ¿Dónde podría combinar los pasos a continuación para crear la tabla final con un número mínimo de pasos intermedios?
# load librarys ------------------------------------------------
library(tidyverse)

# build sample shot data ---------------------------------------
set.seed(123)
shot_df_ex <- tibble(Team_Name = sample(LETTERS[1:5],250, replace = TRUE),
                     Date = sample(as.Date(c("2019-08-01",
                                             "2019-09-01",
                                             "2018-08-01",
                                             "2018-09-01",
                                             "2017-08-01",
                                             "2017-09-01")), 
                                   size = 250, replace = TRUE),
                     Type = sample(c("shot","goal"), size = 250, 
                                   replace = TRUE, prob = c(0.9,0.1))
)

# calculate data ----------------------------------------------
# since every row is a shot, the following function counts shots for ea. team
n_shots <- shot_df_ex %>% 
  count(Team_Name) %>% 
  rename(N_Shots = n)

n_shots

# do the same for goals for each team
n_goals <- shot_df_ex %>% 
  filter(Type == "goal") %>% 
  count(Team_Name,sort = T) %>% 
  rename(N_Goals = n) %>% 
  arrange(Team_Name)

n_goals

# count shots per team per game(date)
n_shots_per_game <- shot_df_ex %>% 
  count(Team_Name,Date)

n_shots_per_game

# count games (dates) per team [ISSUES!!!]
# is there a way to do this piping from the shot_df_ex tibble instead of 
#  using an intermediate tibble?

# count number of games using the tibble created above [DOES NOT WORK]
n_games <- n_shots_per_game %>% 
  count(Team_Name)

n_games #what is this counting? It should be 6 for each.

# this works, but isn't count() just a quicker way to run
#  group_by() %>% summarise()? 
n_games <- n_shots_per_game %>% 
  group_by(Team_Name) %>% 
  summarise(N_Games=n())

n_games

# combine data ------------------------------------------------
# combine columns and add average shots per game
shot_table_ex <- n_games %>% 
  left_join(n_shots) %>% 
  left_join(n_goals)

# final table with final average calculations
shot_table_ex <- shot_table_ex %>% 
  mutate(Shots_per_Game = round(N_Shots / N_Games, 1),
         Goals_per_Game = round(N_Goals / N_Games, 1)) %>% 
  arrange(Team_Name)

shot_table_ex

Respuestas

1 stlba Aug 19 2020 at 23:25

Para 1a, puede simplemente canalizar directamente desde la función tibble () a count (). es decir.

tibble(Team_Name = sample(LETTERS[1:5],250, replace = TRUE),
       Date = sample(as.Date(c("2019-08-01",
                               "2019-09-01",
                               "2018-08-01",
                               "2018-09-01",
                               "2017-08-01",
                               "2017-09-01")), 
                     size = 250, replace = TRUE),
       Type = sample(c("shot","goal"), size = 250, 
                     replace = TRUE, prob = c(0.9,0.1))) %>%
count(Team_Name,Date)

En 1b, count () está usando su columna n(es decir, el número de tiros) como una variable de ponderación, por lo que está sumando el número total de tiros por equipo, no el número de filas. Imprime un mensaje que le dice esto:

Using `n` as weighting variable i Quiet this message with `wt = n` or count rows with `wt = 1`

El uso count(Team_Name, wt=n())le dará el comportamiento que desea.

Editar: parte 2

shot_table_ex <- tibble(Team_Name = sample(LETTERS[1:5],250, replace = TRUE),
                    Date = sample(as.Date(c("2019-08-01",
                                            "2019-09-01",
                                            "2018-08-01",
                                            "2018-09-01",
                                            "2017-08-01",
                                            "2017-09-01")), 
                                  size = 250, replace = TRUE),
                    Type = sample(c("shot","goal"), size = 250, 
                                  replace = TRUE, prob = c(0.9,0.1))) %>%
     group_by(Team_Name) %>%
     summarise(n_shots = n(),
               n_goals = sum(Type == "goal"),
               n_games = n_distinct(Date)) %>%
     mutate(Shots_per_Game = round(n_shots / n_games, 1),
            Goals_per_Game = round(n_goals / n_games, 1))
1 GenesRus Aug 19 2020 at 23:36

1a. A partir de los datos de ejemplo a continuación y usando dplyr, ¿hay alguna manera de calcular los juegos (fechas) por equipo sin usar una tabla intermedia?

Así es como lo haría yo:

shot_df_ex %>% 
  distinct(Team_Name, Date) %>% #Keeps only the cols given and one of each combo
  count(Team_Name)

También puede utilizar unique:

shot_df_ex %>% 
  group_by(Team_Name) %>%
  summarize(N_Games = length(unique(Date))

1b. He incluido mi forma original de calcular n_games que no funcionó. ¿Por qué?

Tu código me funciona. ¿Quizás ahorraste sobre la mesa intermedia? Está contando los 6 esperados por equipo.

  1. A continuación se muestra mi proceso de creación de una tabla de resumen. Entiendo que la canalización está destinada a eliminar la creación de algunas variables / tablas intermedias. ¿Dónde podría combinar los pasos a continuación para crear la tabla final con un número mínimo de pasos intermedios?
shot_df_ex %>% 
  group_by(Team_Name) %>% 
  summarize(
    N_Games = length(unique(Date)),
    N_Shots = sum(Type == "shot"),
    N_Goals = sum(Type == "goal")
  ) %>% 
  mutate(Shots_per_Game = round(N_Shots / N_Games, 1),
         Goals_per_Game = round(N_Goals / N_Games, 1))

Puede utilizar varios pasos de resumen a la vez siempre que no necesite cambiar su agrupación. Aprovechamos aquí (en las sumllamadas) de la interpretación de Verdadero como 1 y Falso como 0. Por lengthsupuesto, nos dará la longitud del vector producido por unique.

esto (count) funciona, pero no count () es solo una forma más rápida de ejecutar group_by ()%>% summary ()?

countes solo una combinación de group_by(col) %>% tally()y tally es esencialmente summarize(x=n())así que sí. :)