【问题标题】:Getting negative ages using lubridate to calculate age from birth date and current date使用 lubridate 从出生日期和当前日期计算年龄得到负年龄
【发布时间】:2019-01-09 01:55:39
【问题描述】:

我的数据看起来像这样。它是一个包含许多人的出生日期(以及其他信息)的数据框。

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

df <- data.frame(
DATE_OF_BIRTH = c("20/10/01" , "15/04/88", "16/12/58", "15/10/91", "09/02/66", "02/07/03", "20/08/96", "22/04/99", "17/04/87", "17/08/56",
                "28/05/40", "26/07/59", "02/04/65", "17/08/93", "01/08/86", "30/07/01", "03/09/75", "17/09/65", "16/02/95", "11/06/03",
                "26/10/64", "25/02/73", "07/02/90", "31/03/38", "05/03/83", "10/02/61", "01/07/40", "15/08/51", "19/12/75", "25/11/58",
                "05/11/81", "05/12/02", "06/05/40", "23/09/69", "17/04/48", "02/07/58", "04/03/98", "26/11/03", "08/01/91", "23/12/07",
                "05/05/01", "23/10/08", "01/01/09", "29/10/63", "26/03/09", "03/02/75", "03/09/04", "17/01/80", "19/03/11", "05/07/83")
)

我想做的是根据每个人的出生日期计算截至 2017 年 7 月 1 日的年龄。

要计算年龄,我使用以下代码:

df <- df %>%
mutate(age = interval(start = dmy(df$DATE_OF_BIRTH), end = dmy('01/07/17')) / 
duration(num = 1, units = "years"))

这个输出对于某些人是正确的,但对于其他人我得到一个负值。对于这些人来说,他们的实际年龄是年龄abs(age)加17的绝对值。

有人能告诉我如何只获得年龄的正值吗?谢谢。

我看到了以下问题:Efficient and accurate age calculation (in years, months, or weeks) in R given birth date and an arbitrary date,但这不包括将负年龄作为输出的问题。

【问题讨论】:

  • 如果出生日期是 1969 年 9 月 23 日(23/09/69),那么他们在 2017 年 7 月 1 日的年龄将为 57 岁。为什么早些年出生的人会得到一个负值作为输出?
  • 你怎么知道他们不是在 2069 年 9 月 23 日出生的?

标签: r lubridate


【解决方案1】:

如果你检查dmy函数的输出

head(df$DATE_OF_BIRTH)
#[1] "20/10/01" "15/04/88" "16/12/58" "15/10/91" "09/02/66" "02/07/03"

head(dmy(df$DATE_OF_BIRTH))
#[1] "2001-10-20" "1988-04-15" "2058-12-16" "1991-10-15" "2066-02-09" "2003-07-02"

R 将 00 - 68 年解释为 2000 - 2068 年,将 69 - 99 年解释为 1969 - 1999。因此,58 被认为是 2058,66 被认为是 2066,但 88 是 1988。

来自?strptime

%y 没有世纪的年份 (00–99)。输入时,值 00 到 68 以 20 为前缀,69 到 99 以 19 为前缀——这是 2004 年和 2008 年 POSIX 标准指定的行为,但他们也说“预计在未来的版本中,默认世纪是从两位数的年份会改变


对于负值,您可以将它们加 100 以获得等效的正值

library(dplyr)
library(lubridate)

df %>%
  mutate(age = interval(start = dmy(DATE_OF_BIRTH), end = dmy('01/07/17')) / 
          duration(num = 1, units = "years"), 
          age = if_else(age < 0, age + 100, age))


#   DATE_OF_BIRTH       age
#1       20/10/01 15.706849
#2       15/04/88 29.230137
#3       16/12/58 58.512329
#4       15/10/91 25.728767
#5       09/02/66 51.356164
#6       02/07/03 14.008219
#7       20/08/96 20.876712
#....

要获得年份之间的日期差异,您还可以像这样使用interval

df %>%
  mutate(age = interval(dmy(DATE_OF_BIRTH), dmy('01/07/17')) / years(1),
         age = if_else(age < 0, age + 100, age))

【讨论】:

    【解决方案2】:

    您需要将数据清理为 lubridate 或 as.Date() 都会产生相似的结果。

    对于大于今天的任何转换年份(不合逻辑的 DoB),将转换日期减去 100 年以使其相关。下面的代码包含上面描述的清理部分。祝您数据分析顺利!

    library(tidyr)
    library(dplyr)
    library(magrittr)
    library(lubridate)
    
    
    library(tidyr)
    library(dplyr)
    library(magrittr)
    library(lubridate)
    
    df <- data.frame(
      DATE_OF_BIRTH = c("20/10/01" , "15/04/88", "16/12/58", "15/10/91", "09/02/66", "02/07/03", "20/08/96", "22/04/99", "17/04/87", "17/08/56",
                        "28/05/40", "26/07/59", "02/04/65", "17/08/93", "01/08/86", "30/07/01", "03/09/75", "17/09/65", "16/02/95", "11/06/03",
                        "26/10/64", "25/02/73", "07/02/90", "31/03/38", "05/03/83", "10/02/61", "01/07/40", "15/08/51", "19/12/75", "25/11/58",
                        "05/11/81", "05/12/02", "06/05/40", "23/09/69", "17/04/48", "02/07/58", "04/03/98", "26/11/03", "08/01/91", "23/12/07",
                        "05/05/01", "23/10/08", "01/01/09", "29/10/63", "26/03/09", "03/02/75", "03/09/04", "17/01/80", "19/03/11", "05/07/83")
    
    )
    
    
    #set the date for comparison
    comparisondate<-as.Date("2017-07-01")
    
    #Retrieve the lubridate format and clean it for incorrect conversions
    df$DOBnew<-dmy(df$DATE_OF_BIRTH)
    #calculate the age
    df$age<-round(as.numeric(difftime(comparisondate,df$DOBnew,units="weeks")/52.25),digits=1)
    df[df$age<0,"DOBnew"]<-df[df$age<0,"DOBnew"] %m-% years(100)
    
    #recalculate age
    df$age<-round(as.numeric(difftime(comparisondate,df$DOBnew,units="weeks")/52.25),digits=1)
    df$age
    
    
    
    [1] 15.7 29.2 58.5 25.7 51.3 14.0 20.8 18.2 30.2 60.8 77.0 57.9 52.2 23.8 30.9 15.9 41.8 51.7 22.3 14.0
    [21] 52.6 44.3 27.4 79.1 34.3 56.3 76.9 65.8 41.5 58.5 35.6 14.6 77.0 47.7 69.1 58.9 19.3 13.6 26.4  9.5
    [41] 16.1  8.7  8.5 53.6  8.3 42.3 12.8 37.4  6.3 33.9
    
    all(df$age>0)
    [1] TRUE
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-09
      • 1970-01-01
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 1970-01-01
      相关资源
      最近更新 更多