Contando observaciones en cada año desde un rango de fecha en dplyr

Digamos que tengo un data.frame consistente en tipo de industria y fechas de inicio y finalización (por ejemplo, para un empleado).

mydf <- data.frame(industry = c("Government", "Education", "Military", "Private Sector", "Government", "Private Sector"),
                   start_date = c("2014-01-01", "2016-02-01", "2012-11-01", "2013-03-01", "2012-12-01", "2011-12-01"),
                   end_date = c("2020-12-01", "2016-10-01", "2014-01-01", "2016-10-01", "2015-10-01", "2014-09-01"))

> mydf
        industry start_date   end_date
1     Government 2014-01-01 2020-12-01
2      Education 2016-02-01 2016-10-01
3       Military 2012-11-01 2014-01-01
4 Private Sector 2013-03-01 2016-10-01
5     Government 2012-12-01 2015-10-01
6 Private Sector 2011-12-01 2014-09-01

Me gustaría crear un gráfico de barras apilada en el que cada año único en el start_date columna está en el eje X (por ejemplo, 2011-2016) y el eje y representa el número total de observaciones (el recuento de filas) representadas en una determinada industria para ese año.

No estoy seguro de cuál es la manera correcta de manipular los datos. marco para permitir esto. Probablemente necesitaría manipular los datos para tener columnas para industry year y count. Pero no estoy seguro de cómo producir las columnas del año de un rango de fechas. ¿Alguna idea?

Pregunta hecha hace 3 años, 5 meses, 0 días - Por pixelprodigy


4 Respuestas:

  • Convertir las columnas de fecha en Date, crear la fecha ' sequence from the 'start_date' to 'end_date' for each row with map2 (de purrr), unnest el list producción, count el year y trama con geom_bar

    library(dplyr)
    library(tidyr)
    library(purrr)
    library(ggplot2)
    mydf %>%
       mutate(across(c(start_date, end_date), as.Date)) %>% 
       transmute(industry, date = map2(start_date, end_date, seq, by = 'day')) %>% 
       unnest(c(date)) %>% 
       count(industry, year = factor(year(date))) %>%
       ggplot(aes(x = year, y = n, fill = industry)) + 
            geom_col() +
            theme_bw()
    

    Si la trama debe ser separada para cada 'industria'

    mydf %>%
       mutate(across(c(start_date, end_date), as.Date)) %>% 
       transmute(industry, date = map2(start_date, end_date, seq, by = 'day')) %>% 
       unnest(c(date)) %>% 
       count(industry, year = factor(year(date))) %>%
       ggplot(aes(x = year, y = n, fill = industry)) + 
            geom_col() + 
            facet_wrap(~ industry) +
            theme_bw()
    

    - ¡Fuera!

    enter image description here


    Como sugirió @IanCampbell, el by para seq puede ser 'year'

    mydf %>%
       mutate(across(c(start_date, end_date), as.Date)) %>% 
       transmute(industry, date = map2(start_date, end_date, seq, by = 'year')) %>% 
       unnest(c(date)) %>% 
       count(industry, year = factor(year(date))) %>%
       ggplot(aes(x = year, y = n, fill = industry)) + 
            geom_col() + 
            facet_wrap(~ industry) +
            theme_bw()
    

    Respondida el Dec 16, 2020 a las 20:09 - por javajedi

    Votos positivos: 0 | Votos negativos: 0

  • ¿Es esto lo que estás buscando? Yo recomendaría usar purrr::pmap crear un nuevo marco de datos con una fila para cada año basado en cada fila de los datos originales.

    Podemos usar el purrr::pmap_dfr para devolver automáticamente un único marco de datos ligado por fila.

    Podemos usar el ~with(list(...), ) truco para poder referenciar columnas por nombre.

    Entonces podemos usar dplyr::count contar por combinaciones de columnas. Entonces es fácil.

    library(dplyr)
    library(purrr)
    library(lubridate)
    library(ggplot)
    mydf %>%
      mutate(across(c(start_date, end_date), as.Date),
             start_year = year(start_date),
             end_year = year(end_date)) %>%
      pmap_dfr(~with(list(...),data.frame(industry,
                                          year = seq(start_year, end_year)))) %>%
      count(year, industry) %>%
    ggplot(aes(x = year, y = n, fill = industry)) + 
      geom_bar(stat="identity")
    

    enter image description here

    Respondida el Dec 16, 2020 a las 20:16 - por scriptsphinx

    Votos positivos: 0 | Votos negativos: 0

  • Para lograr esto en dplyr, primero necesitas generar una secuencia de años entre la fecha de inicio y la fecha de finalización de cada observación. Luego agrupar por año e industria y contar el número de observaciones en cada grupo.

    Aquí tienes un ejemplo de cómo hacerlo:

    R
    library(dplyr)
    library(tidyr)
    
    

    Convertir las fechas a tipo Date

    mydf$start_date <- as.Date(mydf$start_date) mydf$end_date <- as.Date(mydf$end_date)

    Generar secuencia de años para cada observación

    mydf <- mydf %>% mutate(year = map2(start_date, end_date, ~ seq(., .x, by = "year"))) %>% unnest(year)

    Contar observaciones por industria y año

    result <- mydf %>% count(industry, year) %>% arrange(year)

    Crear el gráfico de barras apilado

    library(ggplot2) ggplot(result, aes(x = as.character(year), y = n, fill = industry)) + geom_bar(stat = "identity")

    En este código:

    • Primero convertimos las columnas de fecha a tipo `Date` para facilitar la manipulación de fechas.
    • Luego generamos una secuencia de años entre la fecha de inicio y finalización de cada observación usando la función `map2` de `purrr`.
    • Desagregamos la columna de años generada para que cada fila represente un año único.
    • Contamos el número de observaciones por industria y año.
    • Creamos un gráfico de barras apilado donde el eje X representa los años, el eje Y el recuento de observaciones y las barras están apiladas por industria.

    Con estos pasos, podrás visualizar el número total de observaciones por industria para cada año en un gráfico de barras apilado.

    Respondida el Dec 17, 2020 a las 20:05 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Usando la función cut de dplyr:

    
    library(dplyr)
    
    mydf %>%
      mutate(year = cut(start_date, breaks = "year")) %>%
      group_by(year, industry) %>%
      tally() %>%
      ggplot(aes(x = year, y = n, fill = industry)) +
      geom_bar(stat = "identity")
    

    Explicación:

    cut(start_date, breaks = "year") crea una nueva columna year que asigna cada fila a un año determinado en función de la fecha de inicio. group_by(year, industry) agrupa las filas por año e industria. tally() cuenta el número de observaciones en cada grupo. ggplot() crea un gráfico de barras apiladas con el año en el eje x, el recuento en el eje y y la industria como relleno.

    Usando la función lubridate:

    
    library(lubridate)
    
    mydf %>%
      mutate(year = year(start_date)) %>%
      group_by(year, industry) %>%
      tally() %>%
      ggplot(aes(x = year, y = n, fill = industry)) +
      geom_bar(stat = "identity")
    

    Explicación:

    year(start_date) de lubridate extrae el año de la columna start_date. El resto del código es similar al ejemplo anterior.

    Usando la función tidyr:

    
    library(tidyr)
    
    mydf %>%
      mutate(year = as.numeric(as.character(start_date))) %>%
      pivot_longer(cols = 1:6, names_to = "variable", values_to = "value") %>%
      filter(variable == "start_date") %>%
      mutate(year = year(value)) %>%
      group_by(year, industry) %>%
      tally() %>%
      ggplot(aes(x = year, y = n, fill = industry)) +
      geom_bar(stat = "identity")
    

    Explicación:

    pivot_longer() convierte el marco de datos en formato largo, con una columna para cada variable original. filter(variable == "start_date") selecciona solo las filas que contienen las fechas de inicio. * El resto del código es similar a los ejemplos anteriores.

    Respondida el Dec 17, 2020 a las 20:16 - por Gemini

    Votos positivos: 0 | Votos negativos: 0