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

Pandas按市值中位数划分股票投资组合的比较报错求解

问题场景

硕士学位论文实证环节需基于个股样本构建大小盘投资组合:使用的数据集共218行(对应个股样本)、158列(包含月度市值、交易日期、证券标识等字段),以月度市值中位数为分界阈值,划分高市值、低市值两类组合。
已完成的代码逻辑包括:导入numpy、pandas、matplotlib依赖库,读取本地MarketCap.xlsx数据文件,设置DataFrame索引,查看基础数据信息,计算全字段中位数。运行df_large = df.loc['CM0':'CM-154'] >= dfm语句时触发报错:Invalid comparison between dtype=datetime64[ns] and ndarray。

报错根因
  • 比较范围包含非数值类型字段:计算中位数和做大小比较时未做字段筛选,DataFrame中的datetime64[ns]格式日期列、object格式证券标识列属于非数值字段,无法和数值型中位数数组做大小比较,直接触发类型不兼容错误。
  • 切片逻辑未对齐业务目标:df.loc['CM0':'CM-154']仅按行索引标签做切片,未单独提取市值类数值字段,全字段比较本身不符合“按市值分组”的业务逻辑。
修复方案

按以下步骤调整代码即可解决问题:

  1. 预处理阶段明确字段属性,分离非数值字段与市值计算字段
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 读取数据(保留原有读取逻辑即可)
df = pd.read_excel("MarketCap.xlsx")
# 按原有逻辑设置索引,注意不要把日期、市值类字段误设为索引导致数据丢失
df = df.set_index("证券标识")
# 显式转换日期列格式,避免被识别为数值参与计算
df["日期"] = pd.to_datetime(df["日期"])

# 仅提取月度市值类字段参与中位数计算,不要对全字段算中位数
# 若市值列命名无统一关键词,可手动传入列名列表替换下方推导式
mkt_cap_columns = [col for col in df.columns if "月度市值" in col]
# 按横截面(每个月度维度)计算市值中位数,axis=0对应按列计算
period_median_cap = df[mkt_cap_columns].median(axis=0)
  1. 修正分组判断逻辑,仅对市值字段做阈值比较
# 标记大市值组合:单期市值大于等于当期市值中位数的标的
large_cap_mask = df[mkt_cap_columns] >= period_median_cap
# 标记小市值组合:单期市值小于当期市值中位数的标的
small_cap_mask = df[mkt_cap_columns] < period_median_cap

# 如需提取对应组合的具体持仓、收益数据,可通过掩码关联原表其他字段
large_cap_portfolio = df[large_cap_mask].stack().reset_index(name="对应持仓市值")
small_cap_portfolio = df[small_cap_mask].stack().reset_index(name="对应持仓市值")
  1. 注意事项
  • 所有数值比较、统计量计算环节必须提前过滤日期、证券ID、行业分类这类非数值字段,避免类型冲突
  • 使用loc做行切片前先确认索引已按预期排序,避免标签切片范围和预期的个股样本范围不一致
  • 计算中位数时注意维度选择:横截面分组需按每个月度(列维度)计算中位数,不要误传axis=1按时序维度计算个股中位数,导致分组逻辑错误。

内容的提问来源于stack exchange,提问作者Christian Laely

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:48:17