Pandas创建多层级表格/子表 展开嵌套ohlcv字段实现目标表结构
pandas嵌套K线数据转层级分组表实现方法
核心实现逻辑
分两步完成:先展开嵌套的ohlcv明细为独立行,再将同组上层字段仅保留首行值、其余行置空,达到分组子表的视觉效果。
前置参考:原始数据结构
data_dict = [ { "exchange": "binance", "base": "BTC", "quote": "USDT", "resolution": "1h", "ohlcv": [ {"source_id": 1, "timestamp": 1690000000, "open": 29000, "high": 29100, "low": 28950, "close": 29050, "volume": 123.4}, {"source_id": 2, "timestamp": 1690003600, "open": 29050, "high": 29200, "low": 29020, "close": 29180, "volume": 156.7} ] }, { "exchange": "okx", "base": "ETH", "quote": "USDT", "resolution": "4h", "ohlcv": [ {"source_id": 3, "timestamp": 1690000000, "open": 1800, "high": 1820, "low": 1795, "close": 1815, "volume": 2345.1} ] } ]
步骤1:展开嵌套ohlcv字段为平铺明细
直接用pd.DataFrame.from_dict读取会保留ohlcv为嵌套列,需要先炸开列表、拆分字典字段:
import pandas as pd # 读取原始数据 df = pd.DataFrame(data_dict) # 炸开ohlcv嵌套列表,单条ohlcv对应独立行 df = df.explode("ohlcv", ignore_index=True) # 小数据量拆分ohlcv字典为独立列 ohlcv_cols = ["source_id", "timestamp", "open", "high", "low", "close", "volume"] df[ohlcv_cols] = df["ohlcv"].apply(pd.Series) # 大数据量(10w行以上)替换为下面的高性能写法 # ohlcv_df = pd.json_normalize(df["ohlcv"]) # df = pd.concat([df.drop(columns=["ohlcv"]), ohlcv_df], axis=1) # 删除原始嵌套列 df = df.drop(columns=["ohlcv"])
这一步输出的是全量填充的平铺表,每一行ohlcv都会重复带上对应的exchange、base、quote、resolution值。
步骤2:分组置空非首行的上层字段
按四个上层维度分组,仅保留每组第一行的字段值,其余位置替换为空字符串:
# 定义需要分组展示、仅首行显示的字段 group_cols = ["exchange", "base", "quote", "resolution"] # 组内非首行的分组字段置空 df[group_cols] = df.groupby(group_cols, sort=False, dropna=False)[group_cols].transform( lambda col: [col.iloc[0]] + [""] * (len(col) - 1) ) # 调整列顺序,分组字段放前、明细字段放后 df = df[group_cols + ohlcv_cols]
最终效果参考
| exchange | base | quote | resolution | source_id | timestamp | open | high | low | close | volume |
|---|---|---|---|---|---|---|---|---|---|---|
| binance | BTC | USDT | 1h | 1 | 1690000000 | 29000 | 29100 | 28950 | 29050 | 123.4 |
| 2 | 1690003600 | 29050 | 29200 | 29020 | 29180 | 156.7 | ||||
| okx | ETH | USDT | 4h | 3 | 1690000000 | 1800 | 1820 | 1795 | 1815 | 2345.1 |
注意事项
- 置空后的表仅适合做展示(比如导出Excel、打印报表),如果需要做聚合、筛选等数据计算,建议保留置空前的平铺全量表,避免空值导致计算错误。
- 如果需要空值为
NaN而非空字符串,把transform里的""替换成pd.NA即可。
内容的提问来源于stack exchange,提问作者Himanshu Poddar
相关产品推荐
相关产品推荐

