2012-05-15 108 views
4

我正在處理一些時間數據,我在將時差轉換爲年和月時遇到問題。按年和月計算年齡並融化數據

我的數據看起來或多或少像這樣,

dfn <- data.frame(
Today = Sys.time(), 
DOB = seq(as.POSIXct('2007-03-27 00:00:01'), len= 26, by="3 day"), 
Patient = factor(1:26, labels = LETTERS)) 

首先,我減去出生(DOB)構成今天的數據(Today)的數據。

dfn$ageToday <- dfn$Today - dfn$DOB 

這給了我Time difference in days

dfn$ageToday 
Time differences in days 
    [1] 1875.866 1872.866 1869.866 1866.866 1863.866 
    [6] 1860.866 1857.866 1854.866 1851.866 1848.866 
[11] 1845.866 1842.866 1839.866 1836.866 1833.866 
[16] 1830.866 1827.866 1824.866 1821.866 1818.866 
[21] 1815.866 1812.866 1809.866 1806.866 1803.866 
[26] 1800.866 
attr(,"tzone") 
[1] "" 

這是我問題的第一部分出現的地方; 如何將此差異轉換爲年和月(四捨五入爲幾個月)?(即4.7,4.11等)

我閱讀?difftime手冊頁和?format,但我沒弄明白。

任何幫助,將不勝感激。

此外,我想我的融化最終目標,如果我嘗試使用上面使用此命令的數據幀熔體,

require(plyr) 
require(reshape) 
mdfn <- melt(dfn, id=c('Patient')) 

我得到這個奇怪的警告,我還沒有看到

Error in as.POSIXct.default(value) : 
    do not know how to convert 'value' to class "POSIXct" 

所以,我的第二個問題是, 如何創建時間差異我可以melt與我的POSIXct變量一起嗎?如果我融化沒有dfn$ageToday一切都像一個魅力。

謝謝,埃裏克

回答

5

lubridate封裝使日期和時間的工作,包括尋找時間差,很容易。

library("lubridate") 
library("reshape2") 

dfn <- data.frame(
    Today = Sys.time(), 
    DOB = seq(as.POSIXct('2007-03-27 00:00:01'), len= 26, by="3 day"), 
    Patient = factor(1:26, labels = LETTERS)) 

dfn$diff <- new_interval(dfn$DOB, dfn$Today)/duration(num = 1, units = "years") 

mdfn <- melt(dfn, id=c('Patient')) 
class(mdfn$value) # all values are coerced into numeric 

new_interval()函數計算兩個日期之間的時間差。請注意,有一個功能today()可以替代您使用Sys.time。最後記下duration()函數,該函數創建一個標準時間段,您可以使用該時間段將標準時間間隔除以標準單位的長度,在此情況下,該時間單位爲一年。

如果你想保留的TodayDOB的內容,那麼你可能需要的一切轉化爲character第一,後來再改......

library("lubridate") 
library("reshape2") 

dfn <- data.frame(
    Today = Sys.time(), 
    DOB = seq(as.POSIXct('2007-03-27 00:00:01'), len= 26, by="3 day"), 
    Patient = factor(1:26, labels = LETTERS)) 

# Create standard durations for a year and a month 
one.year <- duration(num = 1, units = "years") 
one.month <- duration(num = 1, units = "months") 

# Calculate the difference in years as float and integer 
dfn$diff.years <- new_interval(dfn$DOB, dfn$Today)/one.year 
dfn$years <- floor(new_interval(dfn$DOB, dfn$Today)/one.year) 

# Calculate the modulo for number of months 
dfn$diff.months <- round(new_interval(dfn$DOB, dfn$Today)/one.month) 
dfn$months <- dfn$diff.months %% 12 

# Paste the years and months together 
# I am not using the decimal point so as not to imply this is 
# a numeric representation of the diference 
dfn$y.m <- paste(dfn$years, dfn$months, sep = '|') 

# convert Today and DOB to character so as to preserve them in melting 
dfn$Today <- as.character(dfn$Today) 
dfn$DOB <- as.character(dfn$DOB) 

# melt using string representation of difference between the two dates 
dfn2 <- dfn[,c("Today", "DOB", "Patient", "y.m")] 
mdfn2 <- melt(dfn2, id=c('Patient')) 

# alternative melt using numeric representation of difference in years 
dfn3 <- dfn[,c("Today", "DOB", "Patient", "diff.years")] 
mdfn3 <- melt(dfn3, id=c('Patient')) 
+0

感謝您回答我的問題。它幾乎在那裏,儘管它幾乎沒有幾個月。它顯示年齡爲2.96年,我希望這是3年,小數點後的任何東西都應該大於.11(如果這有意義?) –

+0

@ eric-d-brean - 我已經擴展了我的第二個代碼片段給你一些方法來逼近你的目標......從這裏走到你想要的目標應該很容易。我給你幾個選擇。 – gauden