2017-08-01 105 views
2

我有这个数据框与来往或离开国家的人的记录。 'date'和'inout'表示一个人在某个日期是在国内旅行('I')还是在外('O')旅行。 id = 1在2008-10-06出国旅行,2009-04-30再次出发。R:如何从时间戳创建连续的日期间隔

数据:

df <- data.frame(id=c(1,1,2,2,2,2,3), 
date=c('2008-10-06','2009-04-30', '1999-07-25','2004-02-27','2005-06-09','2013-07-01','2010-09-07'), 
inout = c('O','I','I','O','I','O','I')) 

    id  date inout 
1 1 2008-10-06  O 
2 1 2009-04-30  I 
3 2 1999-07-25  I 
4 2 2004-02-27  O 
5 2 2005-06-09  I 
6 2 2013-07-01  O 
7 3 2010-09-07  I 

我需要这样一个新的数据帧:

id  start  end destination 
1 1 1900-01-01 2008-10-06  home 
2 1 2008-10-06 2009-04-30  abroad 
3 1 2009-04-30 2017-08-01  home 
4 2 1900-01-01 1999-07-25  abroad 
5 2 1999-07-25 2004-02-27  home 
6 2 2004-02-27 2005-06-09  abroad 
7 2 2005-06-09 2013-07-01  home 
8 2 2013-07-01 2017-08-01  abroad 
9 3 1900-01-01 2010-09-07  abroad 
10 3 2010-09-07 2017-08-01  home 

如果每个人的第一次入住了默认日期1900-01-01开始和最后的住宿结束当前日期(2017-08-01)。 在这个数据框中,Id = 1从1900-01-01到2008-10-06在国内,从2008-10-06到2009-04-30在国外,从2009-04-30到2017-08 -01。

任何人都可以帮助我。如果需要,最好使用dplyr软件包。 致以问候

+0

由于同一'id'有不同的行程,我们可以假设每个行程的开始和结束日期总是出现在连续的行中吗? –

+0

@Oriol,是的。数据总是与df格式相同。 Michael –

回答

0

基地R.相当混乱。似乎工作。

do.call(rbind, lapply(split(df, df$id), function(a) { 
    cbind(id = rep(a$id, length.out = NROW(a)+1), 
      setNames(object = data.frame(do.call(
     rbind, lapply(1:(NROW(a) + 1), function(i) 
      c("1970-01-01", as.character(a$date), "2017-08-01")[i:(i + 1)]) 
    )), 
    nm = c("Start", "End")), 
    Destination = if (a$inout[1] == "O") { 
     rep(x = c("home", "abroad"), 
      length.out = NROW(a) + 1) 
    } else{ 
     rep(x = c("abroad", "home"), 
      length.out = NROW(a) + 1) 
    }) 
})) 
# id  Start  End Destination 
#1.1 1 1970-01-01 2008-10-06  home 
#1.2 1 2008-10-06 2009-04-30  abroad 
#1.3 1 2009-04-30 2017-08-01  home 
#2.1 2 1970-01-01 1999-07-25  abroad 
#2.2 2 1999-07-25 2004-02-27  home 
#2.3 2 2004-02-27 2005-06-09  abroad 
#2.4 2 2005-06-09 2013-07-01  home 
#2.5 2 2013-07-01 2017-08-01  abroad 
#3.1 3 1970-01-01 2010-09-07  abroad 
#3.2 3 2010-09-07 2017-08-01  home 
2

这是我的解决方案。它假设df每行有两个连续的行,因此数据集中有偶数行(否则它将不起作用)。为了测试这一点,那么,我添加一个新行df,其如上面粘贴只有7行,因此将有第四行程不完全:

library(dplyr) 
library(tidyr) 
library(lubridate) 

df %>% 
    mutate(trips = rep(seq(1, n()/2), each = 2)) %>% 
    group_by(trips) %>% 
    spread(inout, date) %>% 
    mutate(start = if_else(date(I) < date(O), I, O), 
     end = if_else(date(I) < date(O), O, I), 
     destination = if_else(date(I) < date(O), 'home', 'abroad')) %>% 
    ungroup %>% 
    select(-c(trips, I, O)) 

##  id  start  end destination 
## <chr>  <fctr>  <fctr>  <chr> 
## 1  1 2008-10-06 2009-04-30  abroad 
## 2  2 1999-07-25 2004-02-27  home 
## 3  2 2005-06-09 2013-07-01  home 
## 4  3 2010-09-07 2012-03-08  home 
+0

对不起 - 每个ID有奇数行。就像在我的df中,只有一行id = 3。还会有3行的id。 –

+0

在这些情况下,您如何填写开始,结束和目的地的信息? –

相关问题