Python中如何将Bloomberg(xbbg)拉取的宽格式价格数据转为长格式?
问题描述
通过Python的xbbg库从Bloomberg获取价格数据,因拉取方式特性得到宽格式数据表(示例如下),需转换为指定的长格式数据,实际数据包含更多日期与交易代码。
原始宽表
| blp | 2023-10-24 | 2023-12-11 | 2023-10-26 | 2024-01-05 | 2024-01-09 | 2024-01-17 | 2024-01-17 |
|---|---|---|---|---|---|---|---|
| DOV US Equity | 132.33 | 131 | |||||
| PRU US Equity | 101.43 | 98 | |||||
| RSG US Equity | 146.02 | ||||||
| CVS US Equity | 81.42 | ||||||
| LEN US Equity | 148.16 | ||||||
| OKE US Equity | 69.06 |
目标长表
| blp | date | price |
|---|---|---|
| DOV US Equity | 10/24/2023 | 132.33 |
| PRU US Equity | 12/11/2023 | 101.43 |
| RSG US Equity | 10/26/2023 | 146.02 |
| CVS US Equity | 1/5/2024 | 81.42 |
| LEN US Equity | 1/9/2024 | 148.16 |
| OKE US Equity | 1/17/2024 | 69.06 |
| DOV US Equity | 1/17/2024 | 131 |
| PRU US Equity | 1/9/2024 | 98 |
现有拉取与转换代码
ticker_list = fin['instrument'].reset_index(drop=True) date_list = fin['declared_date'].reset_index(drop=True) dfs = [] for i in range(len(date_list)): df = blp.bdh(tickers=ticker_list[i], flds=['PX_LAST'],start_date=date_list[i], end_date=date_list[i]) dfs.append(df) # 注意:此处缩进错误,仅会添加最后一次拉取的数据 df_final = pd.concat(dfs,axis=0) df_final df_final_transpose= df_final.transpose() df_final_transpose.index.names = ['blp', 'Field'] df_final_transpose=df_final_transpose.droplevel('Field') df_final_transpose=df_final_transpose.reset_index(drop=False)
fin是包含交易代码(instrument列)和日期(declared_date列)的独立DataFrame,df_final_transpose为尝试转换后的结果,但未得到正确格式。
解决方案
方法一:基于现有宽表转换
如果已得到df_final_transpose,可通过Pandas的melt函数完成宽转长,同时处理空值与日期格式:
import pandas as pd # 宽表转长表 long_df = df_final_transpose.melt( id_vars=['blp'], var_name='date', value_name='price' ) # 过滤空值(原始表中的无效空单元格) long_df = long_df.dropna(subset=['price']) # 转换日期格式为MM/DD/YYYY,去除前导零匹配目标样式 long_df['date'] = pd.to_datetime(long_df['date']).dt.strftime('%m/%d/%Y') long_df['date'] = long_df['date'].apply(lambda x: x.lstrip('0').replace('/0', '/') if '/' in x else x) # 重置索引 long_df = long_df.reset_index(drop=True)
方法二:优化拉取流程,直接生成长表
调整拉取逻辑,在数据获取阶段直接构建长表,避免后续转置操作,更高效且不易出错:
import pandas as pd dfs = [] # 修复原代码的缩进问题,循环内添加数据到列表 for ticker, date in zip(fin['instrument'], fin['declared_date']): df = blp.bdh(tickers=ticker, flds=['PX_LAST'], start_date=date, end_date=date) # 整理单条数据为长格式 df = df.reset_index() df.columns = ['date', 'price'] df['blp'] = ticker dfs.append(df) # 合并所有数据并调整列顺序 long_df = pd.concat(dfs, ignore_index=True) long_df = long_df[['blp', 'date', 'price']] # 转换日期格式 long_df['date'] = pd.to_datetime(long_df['date']).dt.strftime('%m/%d/%Y') long_df['date'] = long_df['date'].apply(lambda x: x.lstrip('0').replace('/0', '/') if '/' in x else x)
内容的提问来源于stack exchange,提问作者bigjdawg43
相关产品推荐
相关产品推荐

