【问题标题】:R sqldf not recognizing posixctR sqldf 无法识别 posixct
【发布时间】:2017-03-12 11:52:42
【问题描述】:

我需要按日期过滤数据使用 sqldf 包

我的表“episodes”有一个字段“created_at,哪个类是 POSIXct。

episodes<-data.frame(created_at=seq(from = as.POSIXct('2016-10-01 01:00:00',tz="GMT"), length.out = 100, by = "days") )

> class(episodes$created_at)
[1] "POSIXct" "POSIXt" 

我得到了第二次约会:

fechaMin=min(episodes$created_at)

library(lubridate)
fechaSig=fechaMin+hours(24)

然后我过滤数据:

 sqldf("SELECT * from episodes e 
where strftime('%Y/%m/%d', e.created_at, 'unixepoch')>='$fechaSig' ")

但是我得到了所有的数据。过滤器不起作用。

我也试过了,没有成功:

    sqldf("SELECT * from episodes e 
where date(e.created_at, 'unixepoch', 'localtime')>='$fechaSig' ")

【问题讨论】:

  • 只有最新版本的 MySQL 支持Datetime,这需要保持POSIXct“在正确的类中”——所以检查你的支持。就其价值而言,PostgreSQL 自 1990 年代以来就拥有它。
  • @DirkEddelbuettel 实际上,在 R 中使用已在 R 中创建的表存在相同的问题 - 请参阅版本。

标签: r date posixct sqldf


【解决方案1】:

首先请注意,库是存储包的存储库,因此 sqldf 是包,而不是库。由于library 命令的不幸名称,这通常会造成混淆。

sqldf 本身不支持 $ 替换。要做到这一点,您需要使用fn$sqldf,其中fn 来自 sqldf 包自动加载的 gsubfn 包。它将这种替换添加到它开头的任何函数的参数中。见?fn

还请注意,SQLite 数据库没有日期或日期时间类,因此 sqldf 只是将 POSIXct 的内部表示发送到 SQLite,即表示自纪元以来相对于 GMT 的秒数的纯数字。请注意,POSIXct 的内部表示始终是自 Epoch 相对于 GMT 以来的秒数,即使它显示相对于不同时区的日期和时间。因此,episodes$created_atfechSig 都从 R 发送到 SQLite,因为 Epoch 相对于 GMT 的秒数即使它们在 R 中都没有以这种方式显示。当 R 从数据库(此时它只是一个普通数字)sqldf 检查字段名称是否最初属于 POSIXct 类,如果是,它会强制将它返回到 POSIXct 的数字。启发式不处理时区,因此它存储为相对于 GMT(所有 POSIXct 变量都是),并显示在本地时区,这是 POSIXct 的默认行为。

在下面的注释中,GMT 比 EDT 早 4 小时,比 EST 早 5 小时,所以答案是正确的。

episodes <- data.frame(created_at = 
 seq(from = as.POSIXct('2016-10-01 01:00:00',tz="GMT"), length.out = 100, by = "days") )

fechaMin <- min(episodes$created_at)

library(lubridate)
fechaSig <- fechaMin + hours(24) # or fechaMin+as.difftime(1,units="hours") w/o lubridate

library(sqldf)
out <- fn$sqldf("select * from episodes where created_at >= $fechaSig")

range(episodes$created_at)
## [1] "2016-10-01 01:00:00 GMT" "2017-01-08 01:00:00 GMT"
range(out$created_at)
## [1] "2016-10-01 21:00:00 EDT" "2017-01-07 20:00:00 EST"

如果您更喜欢只在 GMT 工作,请确保本地时区是 GMT,如下所示:

 Sys.setenv(TZ = "GMT")
 range(out$created_at)
 ## [1] "2016-10-02 01:00:00 GMT" "2017-01-08 01:00:00 GMT"

【讨论】:

  • 谢谢!迟到的评论,但我总是在使用 SQLDF 之前将日期/时间转换为 char,因为 Grothendieck 先生提到了在传入和传出查询时的时区处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-11
  • 2019-07-31
  • 1970-01-01
  • 2011-05-22
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多