计算年龄(以年和月为单位)并融合数据。

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))

首先,我要从今天的日期 (Today) 中减去出生日期 (DOB) 的数据。

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

这可以给我提供“以天为单位的时间差”。
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 的 man 文档,但是仍然没有搞明白。
非常感谢您的帮助。
此外,我想要融合我的最终对象。如果我尝试使用 melt 命令对上面的数据框进行融合,则会出现以下情况:
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"

所以,我的第二个问题是; 我如何创建一个时间差异,可以与我的POSIXct变量一起melt 如果不使用dfn$ageTodaymelt,那么一切都很顺利。

谢谢,Eric

1个回答

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'))

感谢您回答我的问题。它已经接近完成,但它没有将年龄四舍五入到月份。它显示的年龄为2.96岁,我希望它是3岁,小数点后面的数字不应大于0.11(如果这有意义的话?) - Eric Fail
@eric-d-brean -- 我已经扩展了我的第二个代码片段,为您提供了几种逼近目标的方法...从这里到您打算做什么应该很容易。我给您几个选择。 - daedalus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接