如何为Pandas DataFrame的列添加元数据?(价格指标开发场景)
为Pandas DataFrame列添加元数据的解决方案
方法1:利用DataFrame的attrs属性存储列元数据
Pandas的DataFrame和Series自带attrs属性,可直接存储自定义元数据。你可以给整个DataFrame的attrs添加一个字典,用列名作为键,对应的元数据(数据源、计算逻辑等)作为值,实现统一管理。
示例实现
import pandas as pd # 初始化元数据字典 column_metadata = { "datetime": {"type": "原始数据", "description": "时间戳"}, "open": {"type": "原始数据", "description": "开盘价"}, "close": {"type": "原始数据", "description": "收盘价"}, } # 绑定到DataFrame price_df = pd.DataFrame(...) # 你的原始数据 price_df.attrs["column_metadata"] = column_metadata # 在指标计算函数中更新元数据 def average_day_range(price_df: pd.DataFrame, n: int=14, calculation_tool: int=0): # 原有计算逻辑保持不变 function_dict = { 0: {"func": sma, "name": "SMA"}, 1: {"func": ema, "name": "EMA"}, # 其他计算方法... } function, name = function_dict[calculation_tool]["func"], function_dict[calculation_tool]["name"] high_var = function(price_df=price_df, input_mode=3, n=n, from_price=True) low_var = function(price_df=price_df, input_mode=4, n=n, from_price=True) adr = high_var[f'{name}_{n}'] - low_var[f'{name}_{n}'] # 定义新列名并更新元数据 col_name = f'Average Day Range {name}{n}' adr.rename(columns={0: col_name}, inplace=True) if "column_metadata" not in price_df.attrs: price_df.attrs["column_metadata"] = {} price_df.attrs["column_metadata"][col_name] = { "type": "计算指标", "calculation_source": ["high", "low"], "calculation_method": f"{name}({n})高值减去{name}({n})低值", "function": "average_day_range", "params": {"n": n, "calculation_tool": calculation_tool} } return adr # 后续查询某列元数据 print(price_df.attrs["column_metadata"]["Average Day Range SMA14"])
方法2:用MultiIndex列名嵌入关键元数据
如果不想额外维护字典,可以将列名设为多层索引(MultiIndex),把元数据的核心信息(如类型、数据源)放在不同层级,既简洁又能直接识别列的属性。
示例实现
# 转换原始列为多层索引 price_df.columns = pd.MultiIndex.from_tuples([ ("原始数据", "datetime"), ("原始数据", "open"), ("原始数据", "close"), ("原始数据", "high"), ("原始数据", "low"), ("指标", "indicator1"), ("指标", "indicator2") ]) # 在指标函数中用多层命名新列 def average_day_range(price_df: pd.DataFrame, n: int=14, calculation_tool: int=0): # 原有计算逻辑不变 function, name = function_dict[calculation_tool]["func"], function_dict[calculation_tool]["name"] high_var = function(price_df=price_df, input_mode=3, n=n, from_price=True) low_var = function(price_df=price_df, input_mode=4, n=n, from_price=True) adr = high_var[f'{name}_{n}'] - low_var[f'{name}_{n}'] # 多层列名:(类型, 指标名, 数据源) col_name = ("指标", f"ADR_{name}{n}", "源:high/low") adr.rename(columns={0: col_name}, inplace=True) return adr # 快速筛选列 price_df["指标"] # 筛选所有指标列 price_df["指标"].filter(like="ADR") # 筛选所有ADR相关列
方法3:关联JSON文件持久化元数据
如果元数据复杂且需要持久化存储,可以单独维护一个JSON文件,每次新增列时更新文件,使用时读取即可。
示例JSON结构(column_metadata.json)
{ "datetime": { "type": "原始数据", "description": "时间戳" }, "Average Day Range SMA14": { "type": "计算指标", "calculation_source": ["high", "low"], "calculation_method": "SMA(14)高值减SMA(14)低值", "function": "average_day_range", "params": {"n":14, "calculation_tool":0} } }
函数中更新JSON
import json def update_metadata(col_name, metadata, filepath="column_metadata.json"): try: with open(filepath, "r") as f: data = json.load(f) except FileNotFoundError: data = {} data[col_name] = metadata with open(filepath, "w") as f: json.dump(data, f, indent=4) # 在average_day_range中调用 col_name = f'Average Day Range {name}{n}' update_metadata(col_name, { "type": "计算指标", "calculation_source": ["high", "low"], "calculation_method": f"{name}({n})高值减去{name}({n})低值", "function": "average_day_range", "params": {"n": n, "calculation_tool": calculation_tool} })
方法4:自定义DataFrame子类封装元数据管理
如果需要更系统化的元数据管理,可以创建自定义DataFrame子类,内置元数据的添加、查询方法,让逻辑更清晰。
示例实现
class IndicatorDataFrame(pd.DataFrame): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.column_metadata = {} def add_col_metadata(self, col_name, metadata): self.column_metadata[col_name] = metadata def get_col_metadata(self, col_name): return self.column_metadata.get(col_name, "无对应元数据") # 使用自定义类 price_df = IndicatorDataFrame(your_raw_data) # 在指标函数中添加元数据 col_name = f'Average Day Range {name}{n}' price_df.add_col_metadata(col_name, { "type": "计算指标", "calculation_source": ["high", "low"], "calculation_method": f"{name}({n})高值减去{name}({n})低值" }) # 查询元数据 price_df.get_col_metadata("Average Day Range SMA14")
内容的提问来源于stack exchange,提问作者Jakub Szurlej
相关产品推荐
相关产品推荐

