【问题标题】:R/zoo: handle non-unique index entries but not lose data?R/zoo:处理非唯一索引条目但不丢失数据?
【发布时间】:2014-09-12 23:55:51
【问题描述】:

我有一个数据点的 csv 文件(例如金融报价、实验记录等),我的数据有重复的时间戳。这是演示问题的代码:

library(zoo);library(xts)

csv="2011-11-01,50
2011-11-02,49
2011-11-02,48
2011-11-03,47
2011-11-03,46
2011-11-03,45
2011-11-04,44
2011-11-04,43
2011-11-04,42
2011-11-04,41
"

z1=read.zoo(textConnection(csv),sep=',')
w1=to.weekly(z1)
ep=endpoints(z1,"weeks",1)
w1$Volume=period.apply(z1,ep,length)

z2=read.zoo(textConnection(csv),sep=',',aggregate=T)
w2=to.weekly(z2)
ep=endpoints(z2,"weeks",1)
w2$Volume=period.apply(z2,ep,length)

vignette('zoo-faq'),条目 1,告诉我 aggregate=T 摆脱了 zoo 烦人的警告信息。但随后结果发生了变化:

> w1
           z1.Open z1.High z1.Low z1.Close Volume
2011-11-04      50      50     41       41     10
> w2
           z2.Open z2.High z2.Low z2.Close Volume
2011-11-04      50      50   42.5     42.5      4

是否有另一种方法可以消除警告消息但仍获得与 w1 相同的结果? (是的,我知道suppressWarnings(),这是我以前使用的,但我讨厌这个主意。) (我想知道是否将自定义聚合函数传递给 read.zoo,它会返回每天的 OHLCV 数据......但如果这可能的话,我什至无法解决。)

【问题讨论】:

    标签: r zoo


    【解决方案1】:

    您需要一个函数来用“epsilon”增量填充时间戳以使它们 不同的。

    我还编写了一两个基于 Rcpp 的函数来做到这一点。毕竟,时间通常是 POSIXct,它实际上是一个浮点数(在您执行 as.numeric 之后),所以只需循环时间戳,并在与前一个相等的情况下继续添加一个小于 1.0e-7 的小增量POSIXct 本身可以代表什么。每次实际休息时重置累积增量。

    编辑:试试 xts 包中的 make.index.unique()make.time.unique() 函数:

    R> sametime <- rep(Sys.time(), 3)
    R> xts(1:3, order.by=make.time.unique(sametime))
                               [,1]
    2011-12-20 06:52:37.547299    1
    2011-12-20 06:52:37.547300    2
    2011-12-20 06:52:37.547301    3
    R> 
    

    编辑 2: 这是Date 索引对象的另一个示例:

    R> samedate <- rep(Sys.Date(), 5)   # identical dates
    R> xts(1:5, order.by=make.time.unique(as.POSIXct(samedate)))
                               [,1]
    2011-12-19 18:00:00.000000    1
    2011-12-19 18:00:00.000000    2
    2011-12-19 18:00:00.000001    3
    2011-12-19 18:00:00.000002    4
    2011-12-19 18:00:00.000003    5
    R> xts(1:5, order.by=as.Date(make.index.unique(as.POSIXct(samedate))))
               [,1]
    2011-12-20    1
    2011-12-20    2
    2011-12-20    3
    2011-12-20    4
    2011-12-20    5
    R> 
    

    第一个解决方案切换到 POSIXct,它在午夜前六个小时结束,因为 GMT 减去六个小时是我的本地时区。第二个示例使用了双重转换,然后返回到Date --- 然后将其设为唯一。

    【讨论】:

    • 谢谢德克。你如何适应 read.zoo?我刚刚尝试了myglobal&lt;&lt;-0;z3=read.zoo(textConnection(csv),sep=',',FUN=function(v){myglobal&lt;&lt;-(myglobal+1);as.POSIXct(v)+myglobal;}),但 all 我的时间戳只增加了 1 秒。 (+1 最终会是 +1.0e-7,但这种方式在测试时更清晰。)
    • 我在读取之后和创建 xts 或 zoo 对象之前修改了 POSIXct 列,因此我不使用read.zoo
    • 查看我对答案的编辑:来自 xts 的make.time.unique() 帮助。
    • 你好@Dirk我在尝试你的代码时得到这个:UseMethod中的错误(“make.index.unique”):没有适用于'make.index.unique'的方法应用于类的对象"c('POSIXct', 'POSIXt')" (我在 xts 和 zoo 的 2.13.1 版本上;这有关系吗?)
    • 我刚刚检查了我的(不是当前的)XTS SVN 签出,该功能已在 2011 年 1 月添加,并且从那时起有多个 xts 版本。你运行的是什么版本?
    【解决方案2】:

    作为 Dirk 建议的一个简单变体,这应该可以工作

    z0 = read.csv( textConnection(csv), sep=',', header=FALSE )
    z1 = zoo( z0$V2, as.Date(z0$V1) + (1:nrow(z0))*10^-10 )
    

    【讨论】:

    • 那是 a) 太粗糙了,因为你在不需要的地方不断添加 b) 1e-10 太小,所以 POSIXct 仍然认为它是等效的。
    • @Dirk,但它似乎和to.weekly(z1) 一样有效。也可以这样表达:z1 &lt;- read.zoo(text = csv, sep = ",", FUN = function(x) as.Date(x) + seq_along(x) / 10^10)
    • 好像我看错了——这些是Date 而不是POSIXct。我只关心相同的毫秒数,并且添加一个小的 epsilon(大约 1e-7)确实有帮助。以整数表示的日期必须翻转为 double,其中 1e-10 确实可以表示。
    • z2=zoo(z0$V2,as.POSIXct(z0$V1)+(1:nrow(z0)*3.0e-7))z2=read.zoo(textConnection(csv),sep=',',FUN = function(x) as.POSIXct(x) + seq_along(x)*3e-7) 工作得很好(低于 3.0e-7 仍会发出动物园警告)。如果一次性导入大量行,可能会出现问题。
    • 我仍然认为该方法过于“肮脏”,因为偏移量相当糟糕。有关日期类型的示例,请参阅我的答案的另一个编辑。
    猜你喜欢
    • 2013-07-01
    • 2014-05-22
    • 2021-03-05
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    相关资源
    最近更新 更多