You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中按组宽转长后合并生成面板数据集?

R语言:将Excel导入的两行一组宽格式数据转为面板数据集

数据背景

导入的数据集以每两行为一组组织:

  • 每组第1行:列...2到...13存储日期(Excel序列号格式),第1列...1为NA
  • 每组第2行:列...2到...13存储对应日期的公司收益率,第1列...1为公司标识(如F00001092B - Return)

原始数据结构如下:

structure(list(...1 = c(NA, "F00001092B - Return", NA, "F00001092A - Return", 
NA, NA, NA, "F000015112 - Return", NA, "0P0001KFG1 - Return", 
NA, "0P0001KFG2 - Return", NA, "0P0001KG31 - Return"), ...2 = c("43220", 
"7.1993099999999997", "43220", "9.9567099999999993", "-N/A", 
NA, "44074", "5.0628000000000002", "44104", "-7.2036899999999999", 
"44104", "-7.71122", "44074", "3.45444"), ...3 = c(43251, 2.50914, 
43251, 7.08661, NA, NA, 44104, -9.33194, 44135, -1.46045, 44135, 
-1.33158, 44104, -6.43119), ...4 = c(43281, 10.58262, 43281, 
9.74265, NA, NA, 44135, -2.18682, 44165, 19.35054, 44165, 19.1103, 
44135, -2.34933), ...5 = c(43312, -2.08777, 43312, -3.51759, 
NA, NA, 44165, 21.84286, 44196, -2.95694, 44196, -3.05413, 44165, 
21.73591), ...6 = c(43343, 15.81356, 43343, 19.44444, NA, NA, 
44196, -0.38177, 44227, 7.80132, 44227, 7.27166, 44196, -5.5202
), ...7 = c(43373, -3.663, 43373, -4.36047, NA, NA, 44227, 7.00191, 
44255, 5.01423, 44255, 8.44608, 44227, 6.63778), ...8 = c(43404, 
-1.46088, 43404, -3.19149, NA, NA, 44255, 4.64376, 44286, 11.27339, 
44286, 8.3409, 44255, 3.08164), ...9 = c(43434, -7.53453, 43434, 
-9.89011, NA, NA, 44286, 7.97628, 44316, 3.1574, 44316, 3.81616, 
44286, 9.15585), ...10 = c(43465, -3.08588, 43465, -4.00697, 
NA, NA, 44316, 6.94333, 44347, 4.03152, 44347, 2.85649, 44316, 
6.65098), ...11 = c(43496, -1.09915, 43496, -0.54446, NA, NA, 
44347, 5.04557, 44377, 6.4516, 44377, 6.63552, 44347, 2.31668
), ...12 = c(43524, 10.30018, 43524, 12.22628, NA, NA, 44377, 
2.83606, 44408, -3.87638, 44408, -3.88994, 44377, 5.59935), ...13 = c(43555, 
4.50815, 43555, 7.47968, NA, NA, 44408, -3.8261, 44439, -1.63488, 
44439, -0.88845, 44408, -4.49692)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", 
"14"))

需要将其转换为以下结构的长格式面板数据集:

Date  Firm  Return
10/2   X    2.04
10/3   X    2.07
10/2   Y    3.4
10/3   Y    4.2

尝试过的代码(未成功)

#Create Row Identifiers to Group the Data
rets$two_days <- c(0, rep(1:(nrow(rets)-1)%/%2))

#Group by every two days and pivot wider
rets%>%group_by(two_days)%>%
  pivot_longer(cols = !1,names_to = "month", values_to = "ret")

解决方案

核心思路:先将每组的日期行和收益率行配对,分别转长格式后合并,再清理格式。

步骤1:分组并拆分日期与收益率行

先给每行分配组ID,确保每2行归为一组:

library(tidyverse)

# 假设数据已存入rets对象
# rets <- structure(...)  # 你的原始数据结构

# 生成组ID:每2行一组
rets <- rets %>%
  mutate(group_id = rep(seq_len(nrow(.) %/% 2 + 1), each = 2, length.out = nrow(.)))

# 拆分出日期行(组内第1行,...1为NA)和收益率行(组内第2行,...1为公司名)
date_rows <- rets %>% filter(is.na(...1))
return_rows <- rets %>% filter(!is.na(...1))

步骤2:分别转长格式并合并

将日期行和收益率行转为长格式,再按组和列名匹配合并:

# 日期行转长格式:保留group_id,将...2-...13转为Date列
date_long <- date_rows %>%
  pivot_longer(cols = starts_with("..."), names_to = "col_name", values_to = "Date", 
               cols = !c(group_id, ...1)) %>%
  select(group_id, col_name, Date) %>%
  # 过滤无效日期
  filter(!is.na(Date), Date != "-N/A") %>%
  # 将Excel序列号转为标准日期格式
  mutate(Date = as.Date(as.numeric(Date), origin = "1899-12-30"))

# 收益率行转长格式:保留group_id和公司名,将...2-...13转为Return列
return_long <- return_rows %>%
  pivot_longer(cols = starts_with("..."), names_to = "col_name", values_to = "Return",
               cols = !c(group_id, ...1)) %>%
  rename(Firm = ...1) %>%
  select(group_id, col_name, Firm, Return) %>%
  # 过滤无效收益率
  filter(!is.na(Return), Return != "-N/A") %>%
  # 转换为数值型
  mutate(Return = as.numeric(Return))

# 合并日期和收益率数据,去除中间辅助列
panel_data <- date_long %>%
  inner_join(return_long, by = c("group_id", "col_name")) %>%
  select(Date, Firm, Return) %>%
  # 可选:清理Firm名称,去掉末尾的" - Return"
  mutate(Firm = str_remove(Firm, " - Return"))

步骤3:查看结果

运行后panel_data即为目标面板数据集,示例输出:

head(panel_data)
#         Date       Firm   Return
# 1 2018-05-01 F00001092B  7.19931
# 2 2018-06-01 F00001092B  2.50914
# 3 2018-07-01 F00001092B 10.58262
# 4 2018-08-01 F00001092B -2.08777
# 5 2018-09-01 F00001092B 15.81356
# 6 2018-10-01 F00001092B -3.66300

关键说明

  • 原代码失败原因:分组逻辑错误(two_days生成方式不正确),且未区分日期行和收益率行的不同含义,直接转长会导致日期与收益率混淆。
  • 日期转换:Excel日期序列号以1899-12-30为原点,需用as.Date(as.numeric(Date), origin = "1899-12-30")转换为标准日期。
  • 数据清理:过滤NA和-N/A无效值,将收益率转为数值型,公司名称可按需简化。

内容的提问来源于stack exchange,提问作者Matt Flynn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 00:22:01