【问题标题】:Controlling how a date-time object is printed without coercing to a character?控制如何在不强制转换为字符的情况下打印日期时间对象?
【发布时间】:2014-06-20 23:15:44
【问题描述】:

想象一下,我有一个数据框,其中一些列代表日期或时间。使用这些列时,将它们格式化为POSIXlt 对象(或其他明确的日期/时间导向类)很方便。

但是,当我在屏幕上显示这些列或将它们打印到 .csv 时,我会得到完整的 ISO8601 格式时间。我意识到我可以将时间转换为格式化的字符向量,但是我希望使用format(col, format="%m-%Y") 或我想到的任何东西,但我并不热衷于仅仅为了打印而改变对象的类。 R 中的其他对象具有与之关联的打印方法,我们不必显式强制它们。有没有办法用我忽略的 R 对象的任何日期时间类来做到这一点?

编辑:

这是我希望实现的一个最小示例:

a.datetime = Sys.time()
a.datetime

显示:

2014-06-23 09:32:12

这是我在 CSV 中得到的格式

write.csv(data.frame(a.datetime), "example.csv")

如上所述,我意识到我可以手动将其强制转换为具有所需格式的字符,例如:

格式(a.datetime, format="%y-%m") write.csv(data.frame(format(a.datetime, format="%y-%m")), "example.csv")

这不是我想做的;我正在寻找一种方法让对象知道它应该如何打印,而用户不必同时应用该格式和强制到字符向量,如上所示。 (希望这能澄清我所说的改变类型的意思,我指的是输出的类,而不是参数的类)。

我可以尝试定义如下这样的类,例如使用 S3 类,但它仍然不会使用指定的格式打印到 csv。

class(a.datetime) <- c("myclass", class(a.datetime))
attr(a.datetime, 'fmt') <- "%y-%m"
print.myclass <- function(x) print(format(x, format=attr(x,"fmt")))
print.csv(data.frame(a.datetime), "temp.csv")

仍以完整的 ISO 8601 格式打印 csv。

【问题讨论】:

  • 也许您可以发布 dput(head()) 的数据,以便我们准确了解您正在处理的内容。
  • 您对日期时间对象的理解存在缺陷。使用 format(.) 并改变给它的参数。 POSIXct 向量只是带有属性的双精度数,而 POSIXlt 对象是整数值列表,因此无论您使用哪个类,您都需要使用函数来转换为人类可读的形式。 POSIXlt 对象存储在数据帧中是有问题的,因此非常希望将数据时间保存在 POSIXct 中。屏幕显示由print.POSIXt调解。
  • 您的主要兴趣是在调试期间格式化以供检查,还是最终输出/转换?它有所作为。
  • @BondedDust 抱歉,如果我不清楚,但我从未建议它改变论点。我指的是它如何打印到 csv 文件。
  • 如果你想输出到一个csv文件,那么你想要什么其他版本的日期时间对象do?当然,您可以使用 as.numeric 从原点转换为秒数。如果您想要本质上是年月的对象,请查看 zoo 包的 yearmon 类。

标签: r datetime datetime-format


【解决方案1】:

用于写入数据的基本 R 函数没有让用户轻松调整日期时间格式的参数,这很烦人。

不过,有一些方法可以绕过它。当我想快速指定格式并且我不需要担心副作用时,我有时会这样做:

# In bash
Rscript -e "x <- readRDS('foo.rds'); "\
        -e "as.character.POSIXct <- function(x) format(x, format='%Y-%m-%d %H:%M:%S%z'); " \
        -e "write.csv(x, 'foo.csv', row.names=FALSE)"

(我在 shell 命令中显示这一点只是为了强调您希望新的 as.character.POSIXct 方法在使用后消失。)

本质是覆盖POSIXct 类的as.character 方法(出于神秘的原因,覆盖父类POSIXt 将不起作用):

as.character.POSIXct <- function(x)
  format(x, format='%Y-%m-%d %H:%M:%S%z')

这不应该在更大的代码库中完成,因为全局影响可能会溢出到意想不到的代码中!

【讨论】:

    【解决方案2】:

    一些代码来扩展我的评论。 R 是一种函数式语言,因此对向量(列表实际上是向量)的操作不会更改向量,但会返回处理后的结果,并且在数据时间对象的情况下,我们通常会返回字符向量。以下是 POSIXlt 对象的一些视图:

    x <- as.POSIXlt("2000-01-01")
    x
    #[1] "2000-01-01 PST"
    x <- as.POSIXlt("2000-01-01 12:00:00")
    x
    #[1] "2000-01-01 12:00:00 PST"
     str(x)
    # POSIXlt[1:1], format: "2000-01-01 12:00:00"
     mode(x)
    #[1] "list"
     x[[1]]
    #[1] 0
     x[[2]]
    #[1] 0
     x[[3]]
    #[1] 12
     x[[4]]
    #[1] 1
    
    
     unlist(x)
    #   sec    min   hour   mday    mon   year   wday   yday  isdst   zone gmtoff 
    #   "0"    "0"   "12"    "1"    "0"  "100"    "6"    "0"    "0"  "PST"     NA 
     mode(x[[3]])
    #[1] "numeric"
    # x[[10]]; mode(x[[10]])
    #[1] "PST"
    #[1] "character"
    

    请注意,unlist() 进程将列表转换为字符向量。在 R 中,只有列表可以具有混合模式,因此 POSIXlt 对象中的单个字符元素最终会将作为数值存储的所有元素强制转换为字符元素。如上所述,POSIXlt 对象使用起来很棘手,并且数据帧函数通常不能很好地处理它们,因为大多数(行为良好的)数据帧列是原子向量而不是列表。

    【讨论】:

    • 我完全知道对象的类没有改变。请注意,我特别指的是对象的打印方式,例如在 print.csv 或打印到终端。
    猜你喜欢
    • 2013-01-09
    • 1970-01-01
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多