2017-06-19 116 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

相關問題