保存不规则时间序列矩阵的规范形式?
Canonical form to save irregular time series of matrices?
假设一群人p
在i * k
(最终是n维)的二维网格中移动一堆对象o
。
每当有人 p
移动时,我都会拍摄 i x k
网格的快照(这实际上是通过 js 回调发生的)。
所以,对于 p
Alice
和 o
s c("foo", "bar)
,以及 i
,k
各 2 个,在,比如说, 2017-12-24 18:00:00
, 这给出了类似
1 2
1 "foo"
2 "bar"
然后,四秒后,在 2017-12-26 18:00:04
,比方说,
1 2
1 "foo"
2 "bar"
对于其他一些 p
Bob
,我得到了类似的快照,但是,至关重要的是 在不同的时间 ,因为 Bob
选择在不同时间移动对象。
对于大部分分析,我将只查看每个p
的最终(最新)快照,然后愉快地abind()
整个p x i x k
数组中的东西。
但是我也想保留不规则排列的时间序列。
如何在 R 中以巧妙、规范的方式最好地存储这些数据?
因为我不能abind()
跨越不规则的时间点(因为它们因人而异),我目前的做法是只放快照在每个 p
的列表中,比如
data$alice <- list(
`2017-12-24 18-00-00` = matrix(data = c("foo", NA, NA, "bar"), nrow = 2),
`2017-12-24 18-00-04` = matrix(data = c("foo", NA, "bar", NA), nrow = 2))
data$bob <- ...
等等。 (也许,我宁愿使用适当的 lubricate datetimes
作为列表元素属性,但这是细节)。
这工作正常,但感觉 hacky/weird,原因有很多:
- 列表本身不支持时间序列信息,因此将它们添加为列表元素属性感觉很麻烦。
- 该列表很难看出 所有 各个矩阵的秩相同(因为它们必须如此)。 (我想这是不可避免的,因为我不能
abind()
有意义)。
- 我的直觉想法通常很糟糕。必须有更好的方法。
我是时间序列的新手,我只是想确保我不是很愚蠢并且(很糟糕)重新发明轮子来解决这里规范解决的问题。
另外:这将是一个包的一部分,并且是 S3
class,所以我想把它弄好。
注意事项/旁白:
- 我查看了 zoo 包,但是虽然它提供 不规则 时间间隔(我有),但它似乎没有提供 class 对于 不同的 不规则时间间隔。
- 我不想以整齐的格式存储这些数据。我在这里 Jeff Leek;网格的矩阵表示本质上是有意义的,我想保留这一点。还会有一些矩阵代数,如果应用于整洁的数据,那只会产生真正不透明的代码。也就是说,如果我在这里是愚蠢的,以及以整洁的形式存储这种数据的规范方式,我愿意接受它。
Ps.: 为无耻的人道歉pseudo-code/math。希望它仍然有助于使事情更清楚。
我有两个建议,虽然我不知道它们是否 "canonical." 您可以使用 pdata.frame
(来自面板数据的 plm
包)或 tibble
.
设置一些数据:
set.seed(123)
dat <- data.frame(
person = c("Alice", "Alice", "Bob", "Bob"),
time = as.POSIXct(runif(4, 1500000000, 1510000000), origin = "1970-01-01")
)
mats <- lapply(1:4, function(...) matrix(sample(1:4, 4), nc = 2, nr = 2))
pdata.frame
方法将每个矩阵元素存储为一列,除了人员和时间标识符之外,还可以为您提供 i * k
列。
library(plm)
dat_plm <- cbind(dat, as.data.frame(do.call(rbind, lapply(mats, as.vector))))
pdat <- pdata.frame(dat_plm, index = c("person", "time"), row.names = FALSE)
pdat
# person time V1 V2 V3 V4
# 1 Alice 2017-08-04 05:52:13 1 3 2 4
# 2 Alice 2017-08-26 08:13:42 2 4 3 1
# 4 Bob 2017-08-09 08:45:14 4 3 1 2
# 3 Bob 2017-10-28 11:20:55 1 3 2 4
str(pdat)
# Classes ‘pdata.frame’ and 'data.frame': 4 obs. of 6 variables:
# $ person: Factor w/ 2 levels "Alice","Bob": 1 1 2 2
# ..- attr(*, "names")= chr "1" "2" "4" "3"
# ..- attr(*, "index")=Classes ‘pindex’ and 'data.frame': 4 obs. of 2 variables:
# .. ..$ person: Factor w/ 2 levels "Alice","Bob": 1 1 2 2
# .. ..$ time : Factor w/ 4 levels "2017-08-04 05:52:13",..: 1 3 2 4
# <snip>
# - attr(*, "index")=Classes ‘pindex’ and 'data.frame': 4 obs. of 2 variables:
# ..$ person: Factor w/ 2 levels "Alice","Bob": 1 1 2 2
# ..$ time : Factor w/ 4 levels "2017-08-04 05:52:13",..: 1 3 2 4
对我来说tibble
比较优雅:
library(tibble)
dat_tbl <- as_tibble(dat)
dat_tbl$mats <- mats
dat_tbl
# person time mats
# <fctr> <dttm> <list>
# 1 Alice 2017-08-04 05:52:13 <int [2 x 2]>
# 2 Alice 2017-08-26 08:13:42 <int [2 x 2]>
# 3 Bob 2017-10-28 11:20:55 <int [2 x 2]>
# 4 Bob 2017-08-09 08:45:14 <int [2 x 2]>
例如,它允许您拍摄每个人的最新快照:
library(dplyr)
arrange(dat_tbl, time) %>%
group_by(person) %>%
slice(n())
# # A tibble: 2 x 3
# # Groups: person [2]
# person time mats
# <fctr> <dttm> <list>
# 1 Alice 2017-08-26 08:13:42 <int [2 x 2]>
# 2 Bob 2017-10-28 11:20:55 <int [2 x 2]>
假设一群人p
在i * k
(最终是n维)的二维网格中移动一堆对象o
。
每当有人 p
移动时,我都会拍摄 i x k
网格的快照(这实际上是通过 js 回调发生的)。
所以,对于 p
Alice
和 o
s c("foo", "bar)
,以及 i
,k
各 2 个,在,比如说, 2017-12-24 18:00:00
, 这给出了类似
1 2
1 "foo"
2 "bar"
然后,四秒后,在 2017-12-26 18:00:04
,比方说,
1 2
1 "foo"
2 "bar"
对于其他一些 p
Bob
,我得到了类似的快照,但是,至关重要的是 在不同的时间 ,因为 Bob
选择在不同时间移动对象。
对于大部分分析,我将只查看每个p
的最终(最新)快照,然后愉快地abind()
整个p x i x k
数组中的东西。
但是我也想保留不规则排列的时间序列。 如何在 R 中以巧妙、规范的方式最好地存储这些数据?
因为我不能abind()
跨越不规则的时间点(因为它们因人而异),我目前的做法是只放快照在每个 p
的列表中,比如
data$alice <- list(
`2017-12-24 18-00-00` = matrix(data = c("foo", NA, NA, "bar"), nrow = 2),
`2017-12-24 18-00-04` = matrix(data = c("foo", NA, "bar", NA), nrow = 2))
data$bob <- ...
等等。 (也许,我宁愿使用适当的 lubricate datetimes
作为列表元素属性,但这是细节)。
这工作正常,但感觉 hacky/weird,原因有很多:
- 列表本身不支持时间序列信息,因此将它们添加为列表元素属性感觉很麻烦。
- 该列表很难看出 所有 各个矩阵的秩相同(因为它们必须如此)。 (我想这是不可避免的,因为我不能
abind()
有意义)。 - 我的直觉想法通常很糟糕。必须有更好的方法。
我是时间序列的新手,我只是想确保我不是很愚蠢并且(很糟糕)重新发明轮子来解决这里规范解决的问题。
另外:这将是一个包的一部分,并且是 S3
class,所以我想把它弄好。
注意事项/旁白:
- 我查看了 zoo 包,但是虽然它提供 不规则 时间间隔(我有),但它似乎没有提供 class 对于 不同的 不规则时间间隔。
- 我不想以整齐的格式存储这些数据。我在这里 Jeff Leek;网格的矩阵表示本质上是有意义的,我想保留这一点。还会有一些矩阵代数,如果应用于整洁的数据,那只会产生真正不透明的代码。也就是说,如果我在这里是愚蠢的,以及以整洁的形式存储这种数据的规范方式,我愿意接受它。
Ps.: 为无耻的人道歉pseudo-code/math。希望它仍然有助于使事情更清楚。
我有两个建议,虽然我不知道它们是否 "canonical." 您可以使用 pdata.frame
(来自面板数据的 plm
包)或 tibble
.
设置一些数据:
set.seed(123)
dat <- data.frame(
person = c("Alice", "Alice", "Bob", "Bob"),
time = as.POSIXct(runif(4, 1500000000, 1510000000), origin = "1970-01-01")
)
mats <- lapply(1:4, function(...) matrix(sample(1:4, 4), nc = 2, nr = 2))
pdata.frame
方法将每个矩阵元素存储为一列,除了人员和时间标识符之外,还可以为您提供 i * k
列。
library(plm)
dat_plm <- cbind(dat, as.data.frame(do.call(rbind, lapply(mats, as.vector))))
pdat <- pdata.frame(dat_plm, index = c("person", "time"), row.names = FALSE)
pdat
# person time V1 V2 V3 V4
# 1 Alice 2017-08-04 05:52:13 1 3 2 4
# 2 Alice 2017-08-26 08:13:42 2 4 3 1
# 4 Bob 2017-08-09 08:45:14 4 3 1 2
# 3 Bob 2017-10-28 11:20:55 1 3 2 4
str(pdat)
# Classes ‘pdata.frame’ and 'data.frame': 4 obs. of 6 variables:
# $ person: Factor w/ 2 levels "Alice","Bob": 1 1 2 2
# ..- attr(*, "names")= chr "1" "2" "4" "3"
# ..- attr(*, "index")=Classes ‘pindex’ and 'data.frame': 4 obs. of 2 variables:
# .. ..$ person: Factor w/ 2 levels "Alice","Bob": 1 1 2 2
# .. ..$ time : Factor w/ 4 levels "2017-08-04 05:52:13",..: 1 3 2 4
# <snip>
# - attr(*, "index")=Classes ‘pindex’ and 'data.frame': 4 obs. of 2 variables:
# ..$ person: Factor w/ 2 levels "Alice","Bob": 1 1 2 2
# ..$ time : Factor w/ 4 levels "2017-08-04 05:52:13",..: 1 3 2 4
对我来说tibble
比较优雅:
library(tibble)
dat_tbl <- as_tibble(dat)
dat_tbl$mats <- mats
dat_tbl
# person time mats
# <fctr> <dttm> <list>
# 1 Alice 2017-08-04 05:52:13 <int [2 x 2]>
# 2 Alice 2017-08-26 08:13:42 <int [2 x 2]>
# 3 Bob 2017-10-28 11:20:55 <int [2 x 2]>
# 4 Bob 2017-08-09 08:45:14 <int [2 x 2]>
例如,它允许您拍摄每个人的最新快照:
library(dplyr)
arrange(dat_tbl, time) %>%
group_by(person) %>%
slice(n())
# # A tibble: 2 x 3
# # Groups: person [2]
# person time mats
# <fctr> <dttm> <list>
# 1 Alice 2017-08-26 08:13:42 <int [2 x 2]>
# 2 Bob 2017-10-28 11:20:55 <int [2 x 2]>