使用as.yearmon后pivot_wider异常,无法转xts求解决方案
时间序列数据处理问题:pivot_wider异常与xts转换失败
以下是原始数据集代码:
library(zoo) library(xts) df1<-structure(list(Date = structure(c(13523, 13532, 13539, 13551, 13565, 13567, 13579, 13588, 13600, 13607, 13616, 13628, 13637, 13656, 13658, 13670, 13686, 13691, 13698, 13705, 13721, 13735, 13768, 13770, 13783, 13789, 13797, 13811, 13819, 13824, 13838, 13846, 13852, 13860), class = "Date"), Category = c("Type 1", "Type 2", "Type 1", "Type 1", "Type 1", "Type 2", "Type 1", "Type 3", "Type 1", "Type 1", "Type 2", "Type 1", "Type 1", "Type 1", "Type 2", "Type 1", "Type 3", "Type 1", "Type 1", "Type 1", "Type 1", "Type 2", "Type 1", "Type 3", "Type 1", "Type 1", "Type 1", "Type 1", "Type 2", "Type 1", "Type 1", "Type 1", "Type 3", "Type 2"), Value = c(2250, 1200, 625, 2250, 1000, 2750, 2250, 2750, 950, 2000, 1100, 950, 2250, 1000, 2500, 2250, 2500, 1000, 2250, 1200, 700, 2500, 2000, 2500, 900, 2250, 1200, 925, 2500, 2250, 750, 2000, 2500, 950)), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -34L), groups = structure(list( Date = structure(c(13523, 13532, 13539, 13551, 13565, 13567, 13579, 13588, 13600, 13607, 13616, 13628, 13637, 13656, 13658, 13670, 13686, 13691, 13698, 13705, 13721, 13735, 13768, 13770, 13783, 13789, 13797, 13811, 13819, 13824, 13838, 13846, 13852, 13860), class = "Date"), .rows = structure(list(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 33L, 34L), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame" ), row.names = c(NA, -34L), .drop = TRUE))
用户原月度求和代码:
df_month <- df1 %>% group_by(Category, Month = format(Date, "%Y-%m-%d")) %>% summarize(Rolling_Sum = sum(Value)) df_month$Month <- as.yearmon(df_month$Month)
用户尝试以下代码转宽表、替换NA并转换为xts格式,但pivot_wider操作后数据集异常,后续步骤无法正常执行:
# 原错误代码 df_turned <- df_month %>% group_by(Category) %>% pivot_wider(names_from = Category, values_from = Rolling_Sum, id_cols = Month) df_turned <- df_turned %>% replace(.=="NULL", 0) df_turned <- xts(df_turned, order.by = df_turned$Month)
问题原因与修正方案
1. 修正月度分组逻辑
原代码中format(Date, "%Y-%m-%d")保留了具体日期,导致Month列并非真正的月度维度;同时原数据集是分组状态,会干扰后续操作。修正后的月度求和代码:
library(dplyr) library(tidyr) df_month <- df1 %>% ungroup() %>% # 取消原数据的分组状态 mutate(Month = as.yearmon(Date)) %>% # 直接提取年月维度 group_by(Category, Month) %>% summarize(Rolling_Sum = sum(Value), .groups = "drop") # 分组计算后取消分组
2. 正确执行pivot_wider
无需额外group_by(Category),直接使用values_fill参数在转宽表时自动填充NA为0:
df_turned <- df_month %>% pivot_wider( id_cols = Month, names_from = Category, values_from = Rolling_Sum, values_fill = 0 # 直接将缺失值填充为0 )
3. 转换为xts格式
xts要求索引为标准Date类型,需先将yearmon转换为Date,再生成xts对象(注意排除索引列):
# 将yearmon转换为每月第一天的Date格式 df_turned$Month <- as.Date(df_turned$Month) # 生成xts对象,仅传入数值列 xts_obj <- xts(df_turned %>% select(-Month), order.by = df_turned$Month)
完整修正代码
library(zoo) library(xts) library(dplyr) library(tidyr) # 原始数据集(同用户提供的df1) # 步骤1:生成正确的月度求和数据 df_month <- df1 %>% ungroup() %>% mutate(Month = as.yearmon(Date)) %>% group_by(Category, Month) %>% summarize(Rolling_Sum = sum(Value), .groups = "drop") # 步骤2:转宽表并填充NA为0 df_turned <- df_month %>% pivot_wider( id_cols = Month, names_from = Category, values_from = Rolling_Sum, values_fill = 0 ) # 步骤3:转换为xts格式 df_turned$Month <- as.Date(df_turned$Month) xts_obj <- xts(df_turned %>% select(-Month), order.by = df_turned$Month) # 查看结果 print(xts_obj)
内容的提问来源于stack exchange,提问作者alec22
相关产品推荐
相关产品推荐

