如何将宽格式DataFrame转换为按月份分组的长格式数据?
解决DataFrame宽格式转长格式的问题
你现在遇到的问题是把按年份行存储、每月3个数据列(X1-X3对应1月,X4-X6对应2月…)的宽格式DataFrame,转换成包含Year、Month、Value的长格式,之前的gather代码没达到预期,对吧?
问题分析
你之前的代码把每个Xn列单独当成了一个月份,但实际上每3个X列对应同一个月份,所以需要先把X的编号映射到对应的月份分组,再转换成月份名称。
完整解决方案
这里用dplyr、tidyr和stringr包来实现,代码如下:
library(dplyr) library(tidyr) library(stringr) df_L <- df %>% # 可选:过滤掉1970年全为NA的行,如果你需要保留这行可以删除此句 filter(!is.na(X1)) %>% # 将X1-X36列转为长格式,生成X_col(列名)和Value(对应数值)两列 gather(key = "X_col", value = "Value", X1:X36) %>% # 提取X_col中的数字部分,转为数值类型 mutate(Month_num = as.numeric(str_replace(X_col, "X", ""))) %>% # 每3个X对应一个月份,计算对应的月份序号(1-12) mutate(Month_idx = ceiling(Month_num / 3)) %>% # 将月份序号转为缩写名称(Jan/Feb/.../Dec),用month.name可得到全称 mutate(Month = month.abb[Month_idx]) %>% # 保留需要的三列,并按年份和月份排序 select(Year, Month, Value) %>% arrange(Year, Month_idx)
代码解释
filter(!is.na(X1)):因为1970年所有X列都是NA,如果你不需要这一行可以过滤掉;如果需要保留,直接删除这一行即可,结果中1970年的Value会是NA。gather:把宽格式的X1-X36列转换为长格式的键值对,X_col存储原列名(如X1、X2),Value存储对应的数据。str_replace(X_col, "X", ""):提取X后面的数字,得到1到36的连续编号,用于后续分组月份。ceiling(Month_num / 3):通过向上取整,把1-3映射为1(1月),4-6映射为2(2月),以此类推,完美匹配你每月3个数据的规则。month.abb[Month_idx]:调用R内置的月份缩写向量,把1-12的序号转为Jan、Feb这种格式;如果需要全称(如January),替换成month.name即可。select和arrange:最后只保留需要的三列,并按年份和月份排序,让结果和你期望的格式完全一致。
运行这段代码后,你就能得到和示例中一样的长格式数据啦!
内容的提问来源于stack exchange,提问作者Vasker Sharma
相关产品推荐
相关产品推荐

