2017-06-19 77 views
1

我有一个关于数据操作的简单问题。考虑下面的数据集:R中的因子和时间变量的数据集操作

n = c("john","jane","tim","john","jimmy","tim","jane","john","jimmy") 
s = c("2012-03-21","2013-02-12","2014-01-01","2012-05-21","2010-12-17","2012-01-21","2013-03-12","2013-08-21","2010-09-17") 

df = data.frame(n,s) 
    n  s 
1 john 2012-03-21 
2 jane 2013-02-12 
3 tim 2014-01-01 
4 john 2012-05-21 
5 jimmy 2010-12-17 
6 tim 2012-01-21 
7 jane 2013-03-12 
8 john 2013-08-21 
9 jimmy 2010-09-17 

我想创造一个对每个人,我已经计算的月数从最早的时间点数据的第三列。这将显示如下:

  n  s  output 
    1 john 2012-03-21  0 
    2 jane 2013-02-12  0 
    3 tim 2014-01-01  24 
    4 john 2012-05-21  2 
    5 jimmy 2010-12-17  3 
    6 tim 2012-01-21  0 
    7 jane 2013-03-12  1 
    8 john 2013-08-21 17 
    9 jimmy 2010-09-17  0 

正如你所看到的,与约翰例如,最早的时间点是2012-03-21,所以计算出的月数从2012-03-21至2012- 05-21,然后到2013-08-21,并将输出放在适当的行中。

我认为dplyr或应用函数会派上用场,但我发现我正在为不应该太难的东西制作相当多的代码。

谢谢你的帮助。

+1

为什么约翰的最后一点是73.5?应该不是'2013-08-21 - 2012-03-21'是17? – GGamba

+0

对不起计算这些手工并改变了一些日期,使其更容易看到,但一定忘了改变输出。谢谢。 – Tim

回答

2

使用dplyr,我们可以这样做:


n = c("john","jane","tim","john","jimmy","tim","jane","john","jimmy") 
s = c("2012-03-21","2013-02-12","2014-01-01","2012-05-21","2010-12-17","2012-01-21","2013-03-12","2013-08-21","2010-09-17") 
s = as.Date(s) 
df = data.frame(n,s) 


library(dplyr) 

df %>% 
    group_by(n) %>% 
    mutate(out = round(as.integer(difftime(s, s[which.min(s)], units = 'days'))/30, 0)) 
#> # A tibble: 9 x 3 
#> # Groups: n [4] 
#>  n   s out 
#> <fctr>  <date> <dbl> 
#> 1 john 2012-03-21  0 
#> 2 jane 2013-02-12  0 
#> 3 tim 2014-01-01 24 
#> 4 john 2012-05-21  2 
#> 5 jimmy 2010-12-17  3 
#> 6 tim 2012-01-21  0 
#> 7 jane 2013-03-12  1 
#> 8 john 2013-08-21 17 
#> 9 jimmy 2010-09-17  0 

一如往常它的棘手计算的月数,不同月份有不同的长度。

+0

工程很好,感谢您发布这个! – Tim

2

在我的回答,我用的是lubridate包,以确保dfs列没有得到处理字符串或因素:

library(dplyr) 
library(lubridate) 
df$s = as_date(df$s) 

创建开始日期的单独数据帧:

df.startdate = df %>% group_by(n) %>% summarise(start_date = min(s)) 

现在将主要df合并到新建的df.startdate上:

answer = merge(df, df.startdate, by = "n") %>% 
    mutate(output = interval(start_date, s) %/% months(1)) 
+0

这很好,不幸的是不能标记多个答案。感谢您发布和帮助! – Tim

+0

@Tim真的吗?我倾向于赞赏所有对我的问题给予很好回答的人:( – lebelinoz

+1

糟糕,你绝对应该得到赞赏!已经有一段时间了,因为我一直在这里。再次感谢 – Tim