首页 > 解决方案 > 如何处理 R 中具有多索引列的数据帧?

问题描述

假设我想研究关于 3 个生产地点的数量和价格的每日时间序列:我有 6 个时间序列,我可以将它们存储为带有列的 XTS 对象 s1.volume, s1.price, s2.volume, s2.price, s3.volume, s3.price

我没有发现任何类似于我在 Python Pandas 中使用的多索引结构。

所以我使用以下方法来处理我的数据:

library(xts)
library(dygraphs)

# Example of original time series
dates <- seq(from = as.POSIXct("2017-01-01"),
             to = as.POSIXct("2017-12-31"),
             by = "day")
N <- length(dates)
data <- data.frame(s1.volume = rnorm(N, 8, 1),
                 s2.volume = rnorm(N, 10, 1),
                 s3.volume = rnorm(N, 12, 1),
                 s1.price = rnorm(N, 110, 10),
                 s2.price = rnorm(N, 100, 10),
                 s3.price = rnorm(N, 90, 10))
tst_xts <- as.xts(data, order.by = dates)

# Example of manipulation to add a new calculated column for each site
sites <- c("s1", "s2", "s3")
volume_cols <- paste(sites, "volume", sep = ".")
price_cols <- paste(sites, "price", sep = ".")
mult_cols <- paste(sites, "mult", sep = ".")
mult_data <- tst_xts[ , volume_cols] * tst_xts[ , price_cols]
colnames(mult_data) <- mult_cols
tst_xts <- merge(tst_xts, mult_data)

# Function to select columns based on "multiindexing" relying on column names
sel_cols <- function(df, indexes, split = "[.]"){
  cols <- colnames(df)
  cols_split <- strsplit(cols, split)
  cols_res <- do.call(rbind, cols_split)
  is_col_sel <- rep(T, length(cols))
  for (i in 1:length(indexes)){
    index <- indexes[i]
    if (index == "") next()
    is_col_sel <- is_col_sel & (cols_res[, i] == index)
  }
  return(is_col_sel)
}

# Example to rescale prices
sel <- sel_cols(tst_xts, c("", "price"))
tst_xts[ , sel] <- tst_xts[ , sel] / 10

# Example to plot all variables for site s1
sel <- sel_cols(tst_xts, c("s1"))
dygraph(tst_xts[ , sel])

这个 2 级索引示例非常简单,但我经常需要处理具有 4 级索引的数据集。

我觉得这一切都很乏味,想知道是否存在更聪明的结构来处理 R 中的这种多索引数据。

标签: rxts

解决方案


大概您只希望能够访问所有 s1 列、所有 s2 列、所有 s3 列或所有量列、所有价格列或所有 mult 列。

在这种情况下,定义a为 volume/price/mult 和 s1/s2/s3 是 3d 数组的最后两个维度:

ix <- c(matrix(1:9, 3, byrow = TRUE))
dmn <- list(NULL, c("volume", "price", "mult"), c("s1", "s2", "s3"))
a <- array(tst_xts[, ix], c(nrow(tst_xts), 3, 3), dmn)

现在a我们可以提取它的切片,如果需要,将其转换为 xts:

vol <- xts(a[, "volume", ], time(tst_xts))

和 s1 列是:

s1 <- xts(a[,, "s1"], time(tst_xts))

等等,或者说,将卷乘以 10:

a[, "volume", ] <- 10 * a[, "volume", ]

然后根据需要从卷中创建一个 xts 对象,如图所示。


推荐阅读