【问题标题】:Loop over a large list of elements and calculate mean in R循环遍历大量元素并计算 R 中的平均值
【发布时间】:2015-11-01 12:10:01
【问题描述】:

获得我需要的结构以完成我想要的工作所涉及的过程很长,所以请耐心等待。

我创建了一个大的每日元素列表,这些元素被分成不同的星期:

jobs <- sample(1:100, size = 4018, replace = TRUE)
unemployed <- sample(1:100, size = 4018, replace = TRUE)
insurance <- sample(1:100, size = 4018, replace = TRUE)
daily_seq <- seq(as.Date("2004-01-01"), as.Date("2014-12-31"), by = "days")
daily_df <- data.frame(daily_seq, jobs, unemployed, insurance)
library(xts)
daily_xts <- xts(daily_df[-1], order.by = as.Date(daily_seq))
# split daily series into list of daily series split by calendar months:
split_list1 <- split(daily_xts, f = "months", drop = FALSE, k = 1)
# split further into large list of weekly elements with daily data define by week number 1:4:
splitlist1 = NULL
for (i in 1:length(split_list1)) {
intervals <- cut(.indexmday(split_list1[[1]]), c(0, 7, 14, 21, 31), 1:4)
splitlist1[[i]] <- split(split_list1[[i]], intervals)
splitlist1
}

splitlist1 是平衡日历周元素的大型列表。

我实际上想要做的是循环每个“周”并计算每日系列的每周平均值。

我为所需的输出矩阵对象创建了一个日期序列,以对应于我想要的周数:

# date sequence corresponding to weekly averaged dates needed. "v2" is the sequence:
library(lubridate)
v1 <- seq(as.Date("2004-01-01"), as.Date("201-12-31"), by = "week")
lst <- split(v1, list(month(v1), year(v1)), drop=TRUE) # split vector into months and years
days <- substr(v1[1:4],9,10) # substring extracts first 4 observations from a month as the basis of the sequence
v2 <- unlist(lapply(lst, function(y) {
sprintf('%s%s', substr(y[1:4], 1,8), days)}), use.names=FALSE)

# create matrix for desired output:
week_matrix = matrix(NA, nrow = length(v2), ncol = ncol(split_list1[[1]]), dimnames = dimnames(split_list1[[1]][1]))

然后我继续用这些代码行计算相应的平均值:

# loop through each weekly element "j" of daily data and calculate weekly average:
for (i in 1:length(splitlist1)) {
for (j in 1:4) {
for (n in 1:ncol(splitlist1[[1]]$`1`)){
 week_matrix[i,n] <- weighted.mean(splitlist1[[i]]$'j'[,n])
 week_matrix
 }}}

但是,它返回与代码行 Error in 1:ncol(splitlist1[[1]]$j) : argument of length 0 相关的错误,即使在特定周运行此行 j 返回一个整数。 另外,如果我删除这行代码,它会显示一个没有计算的空矩阵。

我已经尝试了我能想到的所有可能的代码行变体,但是我无法产生我想要的输出。我想要的输出是一个矩阵/xts 类型对象,其每周平均值沿对应于v2 日期序列的行和对应于jobs; unemployed; and insurance 的列

你们能帮我解决这个问题吗?!提前致谢。

【问题讨论】:

  • 您的原始时间序列和每周时间序列的长度不同。这可能会导致您的问题。但是,下面的答案使用的代码要少得多,所以请尝试一下!
  • @MikeRSpencer - 对不起,我的错。已修复,但同样的问题。会试一试的。
  • 当你问一个问题时,试着只问一件事。目前这是一个关于列表和手段的问题,但有很多时间序列生成问题。这些应该是单独的问题,而不是“这是我的代码 - 修复它”。

标签: r time split average


【解决方案1】:

与@MikeRSpencer 描述的理念相同。 我正在使用 lubridate 和 dplyr 包:

library(dplyr)
library(lubridate)

jobs <- sample(1:100, size = 4018, replace = TRUE)
unemployed <- sample(1:100, size = 4018, replace = TRUE)
insurance <- sample(1:100, size = 4018, replace = TRUE)
daily_seq <- seq(as.Date("2004-01-01"), as.Date("2014-12-31"), by = "days")
daily_df <- data.frame(daily_seq, jobs, unemployed, insurance)


daily_df %>%
  mutate(WeekOfYear = week(daily_seq)) %>% # obtain week of year
  group_by(WeekOfYear) %>% # group by that 
  select(-daily_seq) %>% # remove variables you don't need to average on
  summarise_each(funs(mean))

请注意,如果您在数据集中包含多年,变量“一年中的周”将重复,您可以使用“一年中的周”和“年”的组合进行分组。

【讨论】:

    【解决方案2】:

    您所拥有的是 dplyr 中的 tapply、by 或聚合类似工具的工作。关键是开发您想要迭代的索引。这是一个使用 tapply 的示例。

    创建你的虚拟数据:

    jobs <- sample(1:100, size = 4018, replace = TRUE)
    unemployed <- sample(1:100, size = 4018, replace = TRUE)
    insurance <- sample(1:100, size = 4018, replace = TRUE)
    daily_seq <- seq(as.Date("2004-01-01"), as.Date("2014-12-31"), by = "days")
    daily_df <- data.frame(daily_seq, jobs, unemployed, insurance)
    

    添加索引以唯一标识每周:

    daily_df$week = rep(seq(as.Date("2004-01-01"), as.Date("2014-12-31"),
        by = "week"), each=7)
    daily_df$YR.week = paste(strftime(daily_df$daily_seq, "%Y"), daily_df_week)
    

    对按年和周分组的每组重复你的平均值:

    tapply(daily_df$jobs, daily_df$YR.week, mean)
    

    【讨论】:

    • 我之前尝试过使用 "%U" 格式,但它假定每个星期和每个月都从星期日开始,这不是这里的情况 - 所以我不得不手动设置一个日期顺序,如果你知道我的意思
    • 好的,方法仍然有效:创建一个包含年和周数的列,并将其用作迭代的索引。我会修改我的答案以反映 - 祝你好运!
    • 这就是交易。我必须以特定月份的每第四周根据每个月的天数(即包括闰年的 28、29、30 和 31 日)而变化的方式来定义每周。
    • 所以基本上,代码中的each=7 并非如此。你觉得我应该在那里做什么?
    • each=7 涉及将周数重复 7 天,而不是整个月。所以我写的方法给你每年每周的平均值,月份无关紧要。
    【解决方案3】:

    我实际上想要做的是循环每个“周”并计算 > 每日系列的每周平均值。

    如果我理解正确,您希望每个月初都以“monthweek”数字 1 开始。 让我们从计算正确的“月周”数开始:

    wk <- function(x) as.numeric(format(x, "%U")); 
    daily_xts$mw <- wk(index(daily_xts)) - wk(as.Date(cut(index(daily_xts),"month"))) +1
    

    请记住,一个月可以分布在 6 个日历周中,因此我们可以将“月周”数字设置为 1-6。2014 年 11 月就是一个例子。

    通过 "monthweek" i 按月获取平均值。 e.对于“工作”:

    daily_xts$mo <- strftime(index(daily_xts), "%m")
    daily_xts$yr <- strftime(index(daily_xts), "%Y")
    monthweek <- aggregate( jobs ~ mw + mo + yr , daily_xts, FUN = mean)
    

    最后 2 行用于“化妆品”并添加一个日期列并从结果数据框中删除现在“不必要的”“mo”和“yr”列。

    monthweek$date <- as.POSIXct(paste(monthweek$yr, monthweek$mo, "01", sep = "-")) 
    monthweek <- monthweek[,c(5,4)]
    

    如果您不想使用“正确”的周数,您可以随时将第 4 周和第 5 周汇总为一组。我把它作为一个练习:-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      • 2017-08-22
      • 1970-01-01
      • 2019-03-09
      • 2021-02-02
      • 1970-01-01
      • 2016-12-22
      相关资源
      最近更新 更多