Expandir rangos definidos por las columnas "desde" y "hasta"

Resuelto edgester asked hace 54 años • 11 respuestas

Este problema también se conoce como "transformar un conjunto de datos de "inicio-fin" en un conjunto de datos de panel".

Tengo un marco de datos que contiene "name"los presidentes de EE. UU., los años en que comienzan y terminan en el cargo ( "from"y "to"columnas). Aquí hay una muestra:

presidents <- data.frame(
  name = c("Bill Clinton", "George W. Bush", "Barack Obama"),
  from = c(1993, 2001, 2009),
  to = c(2001, 2009, 2012)
)
presidents
#>             name from   to
#> 1   Bill Clinton 1993 2001
#> 2 George W. Bush 2001 2009
#> 3   Barack Obama 2009 2012

Quiero crear un marco de datos con dos columnas ( "name"y "year"), con una fila por cada año que un presidente estuvo en el cargo. Por lo tanto, necesito crear una secuencia regular cada año desde " from" hasta "to". Aquí está mi salida esperada:

name           year
Bill Clinton   1993
Bill Clinton   1994
...
Bill Clinton   2000
Bill Clinton   2001
George W. Bush 2001
George W. Bush 2002
... 
George W. Bush 2008
George W. Bush 2009
Barack Obama   2009
Barack Obama   2010
Barack Obama   2011
Barack Obama   2012

Sé que puedo utilizarlo data.frame(name = "Bill Clinton", year = seq(1993, 2001))para ampliar las cosas para un solo presidente, pero no sé cómo repetirlo para cada presidente.

¿Cómo hago esto? Siento que debería saber esto, pero me estoy quedando en blanco.

Actualización 1

Bien, probé ambas soluciones y aparece un error:

foo<-structure(list(name = c("Grover Cleveland", "Benjamin Harrison", "Grover Cleveland"), from = c(1885, 1889, 1893), to = c(1889, 1893, 1897)), .Names = c("name", "from", "to"), row.names = 22:24, class = "data.frame")
ddply(foo, "name", summarise, year = seq(from, to))
Error in seq.default(from, to) : 'from' must be of length 1
edgester avatar Jan 01 '70 08:01 edgester
Aceptado

Aquí tienes una data.tablesolución. Tiene la característica interesante (aunque menor) de dejar a los presidentes en el orden en el que se encuentran:

library(data.table)
dt <- data.table(presidents)
dt[, list(year = seq(from, to)), by = name]
#               name year
#  1:   Bill Clinton 1993
#  2:   Bill Clinton 1994
#  ...
#  ...
# 21:   Barack Obama 2011
# 22:   Barack Obama 2012

Editar: para manejar presidentes con mandatos no consecutivos, use esto en su lugar:

dt[, list(year = seq(from, to)), by = c("name", "from")]
Josh O'Brien avatar Jul 15 '2012 20:07 Josh O'Brien

Puedes utilizar el plyrpaquete:

library(plyr)
ddply(presidents, "name", summarise, year = seq(from, to))
#              name year
# 1    Barack Obama 2009
# 2    Barack Obama 2010
# 3    Barack Obama 2011
# 4    Barack Obama 2012
# 5    Bill Clinton 1993
# 6    Bill Clinton 1994
# [...]

y si es importante que los datos estén ordenados por año, puedes utilizar la arrangefunción:

df <- ddply(presidents, "name", summarise, year = seq(from, to))
arrange(df, df$year)
#              name year
# 1    Bill Clinton 1993
# 2    Bill Clinton 1994
# 3    Bill Clinton 1995
# [...]
# 21   Barack Obama 2011
# 22   Barack Obama 2012

Edición 1: A continuación de la "Actualización 1" de @edgester, un enfoque más apropiado es utilizar adplypara contabilizar a los presidentes con mandatos no consecutivos:

adply(foo, 1, summarise, year = seq(from, to))[c("name", "year")]
flodel avatar Jul 15 '2012 18:07 flodel