"name"
位美国总统(上任和结束任职的年份)("from"
和"to"
列)。这是一个示例:name from to
Bill Clinton 1993 2001
George W. Bush 2001 2009
Barack Obama 2009 2012
...以及
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")
我想要创建具有两列(
"name"
和"year"
)的数据框架,总统任职期间每年都有一行。因此,我需要创建一个每年从“ from
”到"to"
的常规序列。这是我的期望值: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
我知道我可以使用
data.frame(name = "Bill Clinton", year = seq(1993, 2001))
扩展单个总统的职位,但是我不知道如何为每个总统迭代。我该怎么做?我觉得我应该知道这一点,但是我正在画一个空白。
更新1
好,我已经尝试了两种解决方案,但出现错误:
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
#1 楼
您可以使用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
# [...]
,如果按年份对数据进行排序很重要,则可以使用
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
编辑1:继@edgester的“ Update 1”之后,更合适的方法是使用
adply
来说明具有非连续性条款的总裁:adply(foo, 1, summarise, year = seq(from, to))[c("name", "year")]
#2 楼
这是一个data.table
解决方案。它具有很好的(如果是次要的)功能,可以按照提供的顺序保留总统: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
编辑:要处理具有非连续性条款的总统,请改用以下命令:
dt[, list(year = seq(from, to)), by = c("name", "from")]
#3 楼
使用tidyverse
和unnest
的替代map2
方法。 library(tidyverse)
presidents %>%
unnest(year = map2(from, to, seq)) %>%
select(-from, -to)
# name year
# 1 Bill Clinton 1993
# 2 Bill Clinton 1994
...
# 21 Barack Obama 2011
# 22 Barack Obama 2012
编辑:从
tidyr v1.0.0
不能再将新变量作为unnest()
的一部分创建。presidents %>%
mutate(year = map2(from, to, seq)) %>%
unnest(year) %>%
select(-from, -to)
评论
很棒的答案。如此简单,却如此有效。
– JFG123
12月1日1:07
#4 楼
这是一个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: <by row>
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
.. ... ...
#5 楼
另一个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
#6 楼
这是一个快速的R
基本解决方案,其中Df
是您的data.frame
:do.call(rbind, apply(Df, 1, function(x) {
data.frame(name=x[1], year=seq(x[2], x[3]))}))
它给出了有关行名的一些警告,但似乎返回了正确的
data.frame
。 />评论
+1-非常好,尽管我希望它不会抛出这些警告,并且不会产生带有如此丑陋的行名的结果。
–乔什·奥布莱恩(Josh O'Brien)
2012年7月16日在6:07
@ JoshO'Brien,我实际上并不介意行名,它为数据添加了一个层次:我们可以迅速确定比尔·克林顿(Bill Clinton)为美国第42任总统。这在plyr和data.table解决方案中都丢失了。
– A5C1D2H2I1M1N2O1R2T1
2012年7月16日在7:07
#7 楼
使用tidyverse
的另一种选择是将gather
数据转换为长格式,即group_by
,name
并在from
和to
日期之间创建一个序列。 library(tidyverse)
presidents %>%
gather(key, date, -name) %>%
group_by(name) %>%
complete(date = seq(date[1], date[2]))%>%
select(-key)
# A tibble: 22 x 2
# Groups: name [3]
# name date
# <chr> <dbl>
# 1 Barack Obama 2009
# 2 Barack Obama 2010
# 3 Barack Obama 2011
# 4 Barack Obama 2012
# 5 Bill Clinton 1993
# 6 Bill Clinton 1994
# 7 Bill Clinton 1995
# 8 Bill Clinton 1996
# 9 Bill Clinton 1997
#10 Bill Clinton 1998
# … with 12 more rows
#8 楼
使用by
创建一个by
数据列表的列表L
,每个总裁一个data.frame,然后将它们组合在一起。不使用任何软件包。 L <- by(presidents, presidents$name, with, data.frame(name, year = from:to))
do.call("rbind", setNames(L, NULL))
如果您不介意行名,那么最后一行可以简化为:
do.call("rbind", L)
#9 楼
使用dplyr
和tidyr
的另一种解决方案:library(magrittr) # for pipes
df <- data.frame(tata = c('toto1', 'toto2'), from = c(2000, 2004), to = c(2001, 2009))
# tata from to
# 1 toto1 2000 2001
# 2 toto2 2004 2009
df %>%
dplyr::as.tbl() %>%
dplyr::rowwise() %>%
dplyr::mutate(combined = list(seq(from, to))) %>%
dplyr::select(-from, -to) %>%
tidyr::unnest(combined)
# tata combined
# <fct> <int>
# 1 toto1 2000
# 2 toto1 2001
# 3 toto2 2004
# 4 toto2 2005
# 5 toto2 2006
# 6 toto2 2007
# 7 toto2 2008
# 8 toto2 2009
评论
您的解决方案适用于大多数数据。请查看我的更新。
– Edgester
2012年7月16日在1:04
adply解决方案是唯一没有错误“ seq.default(from,to)中的错误:'from'的长度必须为1”的解决方案。感谢您提供有效的解决方案。您能否解释为什么其他解决方案出现“必须长度为1”错误?
– Edgester
2012年8月7日在0:45
@JoshOBrien和我的都在您的示例数据上工作,因此如果不查看完整数据就很难说。也许您可以将数据精简为一个重现您看到的错误的子集?这样我们也许可以提供帮助。
–弗洛德尔
2012年8月7日17:30