【问题标题】:Operations on Date Field from online data - sqldf来自在线数据的日期字段的操作 - sqldf
【发布时间】:2016-10-22 06:29:31
【问题描述】:

我正在使用具有日期的在线数据集。我正在尝试使用 R (sqldf) 基于日期执行操作,但它不起作用。我可以使用其他包解决我的问题,但我会通过使用 SQL 查询限制我的分析来解决这个问题。

我将首先使用一个简单的示例和一个本地数据集来展示我想要做什么:

library(sqldf)
Name <- c('A', 'B', 'C', 'D', 'E')
DOB <- c('1989-08-19','1993-07-14', '1982-12-16', '1934-11-04', '2010-02-19')
dt1 <- data.frame(Name, DOB)
dt1
str(dt1)

使用这个我可以使用 sqldf 计算年龄并得到正确的结果:

sqldf("select name, current_date, DOB from dt1")
sqldf("select name, current_date, DOB, current_date-DOB as AGE from dt1")
sqldf("select name, current_date, DOB, current_date-DOB as AGE from dt1 
  where DOB >'1990-01-01'")

我在 Google 驱动器中创建了完全相同的数据集,我正在尝试复制上述脚本。

library(gsheet)
dt2 <- gsheet2tbl("https://docs.google.com/spreadsheets/d/1E3lFgsee9FZL0NERAyDwRYvYqpjsMJ-9aLzj9rJcBc4/edit?usp=sharing")
dt2
str(dt2)
sqldf("select name, current_date, DOB from dt2")
sqldf("select name, current_date, DOB, current_date-DOB as AGE from dt2")
sqldf("select name, current_date, DOB, current_date-DOB as AGE from dt2 
  where DOB >'1990-01-01'")

它以千年为单位返回年龄!

试图改变日期格式

dt2 <- gsheet2tbl("Same as Above")
str(dt2)
dt2
dt2$DOB <- as.Date(dt$DOB, "%y/%m/%d")
str(dt2)
dt2

由于 DOB 已变为 NA,我被卡住了,所以我尝试了另一种日期格式

dt2 <- gsheet2tbl("Same as Above")
str(dt2)
dt2
dt2$DOB <- as.Date(dt2$DOB, "%y-%m-%d")
str(dt2)
dt2

同样的问题,所以我尝试转换为因子

dt2 <- gsheet2tbl("Same as above")
str(dt2)
dt2
dt2$DOB <- as.factor(dt2$DOB)
str(dt2)
dt2
sqldf("select name, current_date, DOB from dt2")
sqldf("select name, current_date, DOB, current_date-DOB as AGE from dt2")
sqldf("select name, current_date, DOB, current_date-DOB as AGE from dt2 
  where DOB >'1990-01-01'")

回到第一方,年龄以千年为单位! 任何有关如何使用 SQL 查询解决此问题的建议将不胜感激。 谢谢。

PS 当我下载数据并将其导入为 csv 时,我遇到了同样的问题。

【问题讨论】:

    标签: r sqldf


    【解决方案1】:

    如果您对字符串变量进行操作,您的算法将不会为您提供正确的 AGE。你可以这样做:

    library(gsheet)
    dt2 <- gsheet2tbl("https://docs.google.com/spreadsheets/d/1E3lFgsee9FZL0NERAyDwRYvYqpjsMJ-9aLzj9rJcBc4/edit?usp=sharing")
    
    # Convert date to a "real date"
    dt2$DOB <- as.Date(dt2$DOB, "%m/%d/%Y")
    
    # Add today's date, also as a "real date"
    dt2$today <- as.Date(Sys.Date())
    
    # Perform calculation for age
    sqldf("select name, today, DOB, floor((today-DOB)/365.25) as AGE from dt2")
    

    结果

      Name      today        DOB AGE
    1    A 2016-06-20 1989-08-19  26
    2    B 2016-06-20 1993-07-14  22
    3    C 2016-06-20 1982-12-16  33
    4    D 2016-06-20 1934-11-04  81
    5    E 2016-06-20 2010-02-19   6
    

    根据 OP 的评论进行编辑...

    对于第三个查询,我们可以在表中包含截止日期,就像我们对 today 列所做的那样,或者使用以下替代方法:

    sqldf(paste0("select name, today, DOB, floor((today-DOB)/365.25) as AGE from dt2 where DOB > ", 
                 as.integer(as.Date('1990-01-01'))))
    

    第三次查询的结果

      Name      today        DOB AGE
    1    B 2016-06-20 1993-07-14  22
    2    E 2016-06-20 2010-02-19   6
    

    【讨论】:

    • 这适用于第一个和第二个查询,但是当我尝试第三个查询时它会生成零行。 > sqldf("select name, today, DOB, floor((today-DOB)/365.25) as AGE from dt2 where DOB >'1990-01-01'") [1] 命名今天的 DOB AGE (或0 长度的 row.names)
    • 对...请看我的编辑...因为 DOB 列是数字的(尽管它以人类可读的格式显示),您需要将它与另一个数字日期进行比较。
    • 有效!感谢您的宝贵时间。
    • 不客气!请不要忘记投票和/或接受此答案作为解决方案,它也会为您赢得代表积分。
    猜你喜欢
    • 2019-10-31
    • 2020-05-23
    • 1970-01-01
    • 2014-11-01
    • 2021-09-24
    • 2012-08-16
    • 2021-04-08
    • 1970-01-01
    • 2011-11-01
    相关资源
    最近更新 更多