【问题标题】:Partitioning data set by time intervals in R在 R 中按时间间隔对数据集进行分区
【发布时间】:2012-07-07 07:46:00
【问题描述】:

我有一些按小时观察的数据。我正在尝试按天甚至每周间隔对这些数据进行子集化。我不确定如何在R 中继续执行此任务。

数据样本如下。

date                                 obs
2011-10-24 01:00:00                  12
2011-10-24 02:00:00                  4
2011-10-24 19:00:00                  18
2011-10-24 20:00:00                  7
2011-10-24 21:00:00                  4
2011-10-24 22:00:00                  2
2011-10-25 00:00:00                  4
2011-10-25 01:00:00                  2
2011-10-25 02:00:00                  2
2011-10-25 15:00:00                  12
2011-10-25 18:00:00                  2
2011-10-25 19:00:00                  3
2011-10-25 21:00:00                  2
2011-10-25 23:00:00                  9
2011-10-26 00:00:00                  13
2011-10-26 01:00:00                  11

【问题讨论】:

  • 你能提供一个你正在尝试做什么的例子吗? “按天或周间隔子集”可以用几种不同的方式来解释。
  • 我正在尝试根据时间限制获取数据的子集(非聚合)。
  • 是的,我知道您正在尝试获取子集,但是您想按日历周、从特定时间点开始的一周等进行子集吗?
  • 对不起,我应该更清楚。我想要按日历周划分。

标签: r dataset partitioning


【解决方案1】:

首先我输入了多个空格替换为制表符的数据。

dat$date <- as.POSIXct(dat$date, format="%Y-%m-%d %H:%M:%S")
split(dat , as.POSIXlt(dat$date)$yday)
# Notice these are not the same functions
#---------------------
$`296`
                 date obs
1 2011-10-24 01:00:00  12
2 2011-10-24 02:00:00   4
3 2011-10-24 19:00:00  18
4 2011-10-24 20:00:00   7
5 2011-10-24 21:00:00   4
6 2011-10-24 22:00:00   2

$`297`
                  date obs
7  2011-10-25 00:00:00   4
8  2011-10-25 01:00:00   2
9  2011-10-25 02:00:00   2
10 2011-10-25 15:00:00  12
11 2011-10-25 18:00:00   2
12 2011-10-25 19:00:00   3
13 2011-10-25 21:00:00   2
14 2011-10-25 23:00:00   9

$`298`
                  date obs
15 2011-10-26 00:00:00  13
16 2011-10-26 01:00:00  11

POSIXlt 类在数据帧中不能很好地工作,但它可以非常方便地创建基于时间的组。这是一个具有以下索引的列表结构:'yday'、'wday'、'year'、'mon'、'mday'、'hour'、'min'、'sec' 和 'isdt'。 cut.POSIXt 函数在其他自然边界处添加分割;例如

?cut.POSIXt
  split(dat , cut(dat$date, "week") )

如果您想在日期内求和:

tapply(dat$obs, as.POSIXlt(dat$date)$yday, sum)
#-------
296 297 298 
 47  36  24 

【讨论】:

  • 谢谢你,@DWin。每周你会怎么做?
  • 数据框有什么解决方案吗?
  • 对第一个问题使用 cut(dat$date,breaks="week")。对于第二个问题....嗯? .... 那是一个数据框。
  • 我的第二个问题是关于 POSIXit 在数据帧中无法正常工作的句子。
  • 我只是建议不要使用 POSIXlt 作为数据帧内容的类。您当然可以使用POSIXctPOSIXlt 作为输出策略。这就是它的真正用途。
【解决方案2】:

我会使用时间序列类,例如 xts

dat <- read.table(text="2011-10-24 01:00:00                  12
2011-10-24 02:00:00                  4
2011-10-24 19:00:00                  18
2011-10-24 20:00:00                  7
2011-10-24 21:00:00                  4
2011-10-24 22:00:00                  2
2011-10-25 00:00:00                  4
2011-10-25 01:00:00                  2
2011-10-25 02:00:00                  2
2011-10-25 15:00:00                  12
2011-10-25 18:00:00                  2
2011-10-25 19:00:00                  3
2011-10-25 21:00:00                  2
2011-10-25 23:00:00                  9
2011-10-26 00:00:00                  13
2011-10-26 01:00:00                  11", header=FALSE, stringsAsFactors=FALSE)

xobj <- xts(dat[, 3], as.POSIXct(paste(dat[, 1], dat[, 2])))

xts 子集非常直观。对于“2011-10-25”的所有数据,请执行此操作

xobj["2011-10-25"]
#                    [,1]
#2011-10-25 00:00:00    4
#2011-10-25 01:00:00    2
#2011-10-25 02:00:00    2
#2011-10-25 15:00:00   12
#2011-10-25 18:00:00    2
#2011-10-25 19:00:00    3
#2011-10-25 21:00:00    2
#2011-10-25 23:00:00    9

您还可以像这样子化时间跨度(包括 2011-10-24 和 2011-10-25 之间的所有数据)

xobj["2011-10-24/2011-10-25"]

或者,如果您想要 2011 年 10 月的所有数据,

xobj["2011-10"]

如果您想获取 19:00 到 20:00 之间任何一天的所有数据,

xobj['T19:00:00/T20:00:00']
#                    [,1]
#2011-10-24 19:00:00   18
#2011-10-24 20:00:00    7
#2011-10-25 19:00:00    3

您可以使用endpoints 函数查找属于某个时间段(“小时”、“天”、“周”等)最后一行的行

endpoints(xobj, "days")
[1]  0  6 14 16    

或者您可以转换为较低的频率

to.weekly(xobj)
#           xobj.Open xobj.High xobj.Low xobj.Close
#2011-10-26        12        18        2         11
to.daily(xobj)
#           xobj.Open xobj.High xobj.Low xobj.Close
#2011-10-25        12        18        2          2
#2011-10-26         4        12        2          9
#2011-10-26        13        13       11         11

请注意,上面创建了开盘价、最高价、最低价和收盘价列。如果你只想要端点的数据,你可以使用OHLC=FALSE

to.daily(xobj, OHLC=FALSE)
#           [,1]
#2011-10-25    2
#2011-10-26    9
#2011-10-26   11

如需更多基本子集等,请访问http://www.quantmod.com/examples/

正如@JoshuaUlrich 在 cmets 中提到的,split.xts 非常有用。

您可以按天(或周、月等)拆分,应用一个函数,然后重新组合

split(xobj, 'days') #create a list where each element is the data for a different day
#[[1]]
#                    [,1]
#2011-10-24 01:00:00   12
#2011-10-24 02:00:00    4
#2011-10-24 19:00:00   18
#2011-10-24 20:00:00    7
#2011-10-24 21:00:00    4
#2011-10-24 22:00:00    2
#
#[[2]]
#                    [,1]
#2011-10-25 00:00:00    4
#2011-10-25 01:00:00    2
#2011-10-25 02:00:00    2
#2011-10-25 15:00:00   12
#2011-10-25 18:00:00    2
#2011-10-25 19:00:00    3
#2011-10-25 21:00:00    2
#2011-10-25 23:00:00    9
#
#[[3]]
#                    [,1]
#2011-10-26 00:00:00   13
#2011-10-26 01:00:00   11

假设您只需要每天的第一个值。 split 白天,lapply first 函数和 rbind 回到一起。

do.call(rbind, lapply(split(xobj, 'days'), first))
#                    [,1]
#2011-10-24 01:00:00   12
#2011-10-25 00:00:00    4
#2011-10-26 00:00:00   13

【讨论】:

  • 别忘了split.xtssplit(xobj, "days")
  • @GSee,谢谢!出于某种原因运行:xobj &lt;- xts(dat[, 3], as.POSIXct(paste(dat[, 1], dat[, 2]))) 给了我一个错误:order.by requires an appropriate time-based object。有什么建议吗?
  • 函数xts的第一个参数应该是数据,第二个参数应该是时间索引。如果您在我的答案中复制并粘贴整个第一个代码块,它应该可以工作(并且对我有用),因为前 2 列是日期和时间,第 3 列是数据。 zooxts 包中的小插曲将帮助您弄清楚如何将数据转换为 xts。或者,如果您提供数据的dput,我会针对您的具体数据更新我的答案。
猜你喜欢
  • 1970-01-01
  • 2021-07-07
  • 1970-01-01
  • 1970-01-01
  • 2021-09-16
  • 2015-04-13
  • 1970-01-01
  • 2017-11-24
  • 2023-03-16
相关资源
最近更新 更多