Amplíe los rangos definidos por las columnas “desde” y “hasta”

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

 name from to Bill Clinton 1993 2001 George W. Bush 2001 2009 Barack Obama 2009 2012 

… y el resultado de dput :

 dput(tail(presidents, 3)) structure(list(name = c("Bill Clinton", "George W. Bush", "Barack Obama" ), from = c(1993, 2001, 2009), to = c(2001, 2009, 2012)), .Names = c("name", "from", "to"), row.names = 42:44, class = "data.frame") 

Quiero crear un dataframe 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 con cada año desde ” from ” hasta "to" . Aquí está mi esperado:

 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 usar data.frame(name = "Bill Clinton", year = seq(1993, 2001)) para expandir las cosas para un solo presidente, pero no puedo encontrar la manera de iterar para cada presidente.

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

Actualización 1

De acuerdo, probé ambas soluciones y recibo 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 

Puedes usar el paquete plyr :

 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 se clasifiquen por año, puede usar la función de arrange :

 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 

Editar 1: la siguiente "Actualización 1" de @ edgester, un enfoque más apropiado es usar adply para tener en cuenta a los presidentes con términos no consecutivos:

 adply(foo, 1, summarise, year = seq(from, to))[c("name", "year")] 

Aquí hay una solución de data.table . Tiene la característica agradable (aunque menor) de dejar a los presidentes en su orden de suministro:

 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 términos no consecutivos, use esto en su lugar:

 dt[, list(year = seq(from, to)), by = c("name", "from")] 

Aquí hay una solución dplyr :

 library(dplyr) # the data presidents <- structure(list(name = c("Bill Clinton", "George W. Bush", "Barack Obama" ), from = c(1993, 2001, 2009), to = c(2001, 2009, 2012)), .Names = c("name", "from", "to"), row.names = 42:44, class = "data.frame") # the expansion of the table presidents %>% rowwise() %>% do(data.frame(name = .$name, year = seq(.$from, .$to, by = 1))) # the output Source: local data frame [22 x 2] Groups:  name year (chr) (dbl) 1 Bill Clinton 1993 2 Bill Clinton 1994 3 Bill Clinton 1995 4 Bill Clinton 1996 5 Bill Clinton 1997 6 Bill Clinton 1998 7 Bill Clinton 1999 8 Bill Clinton 2000 9 Bill Clinton 2001 10 George W. Bush 2001 .. ... ... 

h / t: https://stackoverflow.com/a/24804470/1036500

Aquí hay una solución rápida de base R , donde Df es su data.frame :

 do.call(rbind, apply(Df, 1, function(x) { data.frame(name=x[1], year=seq(x[2], x[3]))})) 

Da algunas advertencias sobre nombres de fila, pero parece devolver el data.frame correcto.

Otra solución base :

 l <- mapply(`:`, d$from, d$to) data.frame(name = d$name[rep(1:nrow(d), lengths(l))], year = unlist(l)) # name year # 1 Bill Clinton 1993 # 2 Bill Clinton 1994 # ...snip # 8 Bill Clinton 2000 # 9 Bill Clinton 2001 # 10 George W. Bush 2001 # 11 George W. Bush 2002 # ...snip # 17 George W. Bush 2008 # 18 George W. Bush 2009 # 19 Barack Obama 2009 # 20 Barack Obama 2010 # 21 Barack Obama 2011 # 22 Barack Obama 2012