问题描述
我遇到了一个问题,找不到毛病,请帮助。
源代码:
df = getfundamentals(query(
valuation.code,
valuation.market_cap,
valuation.pb_ratio,
valuation.pe_ratio,
indicator.inc_return
).filter(
valuation.code.in(context.universe),
valuation.pb_ratio>0,
valuation.pe_ratio>0,
indicator.inc_return>0
)).dropna()
df_size = df.sort(columns='market_cap')
list_size = df_size['code']
print list_size
for stock in list_size:
print stock, list_size.index(stock)
输出结果如下:
2014-01-02 09:30:00 - INFO - 1315 600455.XSHG
...
Name: code, dtype: object
2014-01-02 09:30:00 - INFO - 600455.XSHG
2014-01-02 09:30:00 - ERROR - Traceback (most recent call last):
File "jqboson/core/entry.py", line 340, in _run
engine.start()
File "jqboson/core/engine.py", line 206, in start
self._start()
File "jqboson/core/engine.py", line 235, in _start
self._dispatcher.start()
File "jqboson/core/dispatcher.py", line 206, in start
self._loop()
File "jqboson/core/dispatcher.py", line 186, in _loop
self._event_bus.emit(ev[1])
File "jqboson/core/bus.py", line 35, in emit
ret.append(call(event))
File "jqboson/core/strategy.py", line 278, in _wrapper
self._context.strategy_options.get_fq_ref_date(self._context.current_dt)))
File "user_code.py", line 42, in handle_data
print stock, list_size.index(stock)
TypeError: 'Int64Index' object is not callable
600455.XSHG 在list_size里面,是第一个,怎么会报错Int64Index?
解决方案
错误原因分析
您遇到的错误 TypeError: 'Int64Index' object is not callable 是因为混淆了 Pandas Series 和 Python 原生 List 的用法。
在您的代码中:
list_size = df_size['code']
这里的 list_size 实际上并不是一个 Python 的 list,而是一个 Pandas Series 对象(从 DataFrame 中提取的一列)。
- 在 Python 原生的
list中,.index()是一个方法,用于查找元素的位置,例如my_list.index(value)。 - 但在 Pandas Series 中,
.index是一个属性,它返回的是这个 Series 的索引对象(在您的情况下是Int64Index)。
当您尝试执行 list_size.index(stock) 时,Python 解释器认为您试图把一个索引对象当作函数来调用(加上了括号 ()),因此抛出了 'Int64Index' object is not callable 的错误。
解决方法
要解决这个问题,您需要将 Pandas Series 转换为真正的 Python list,然后再调用 .index() 方法。有以下两种常用的修改方式:
方法一:使用 .tolist() 转换为列表(推荐)
在提取列时,直接将其转换为 Python 列表:
# 将 Series 转换为 list
list_size = df_size['code'].tolist()
print list_size
for stock in list_size:
print stock, list_size.index(stock)
方法二:使用 list() 函数转换
# 使用 list() 强制转换
list_size = list(df_size['code'])
print list_size
for stock in list_size:
print stock, list_size.index(stock)
方法三:使用 enumerate 遍历(更高效的 Pythonic 写法)
如果您只是想在遍历时同时获取元素的索引和值,使用 enumerate 是最高效且最优雅的方式,不需要调用 .index():
list_size = df_size['code'].tolist()
# enumerate 会自动生成索引 i 和对应的值 stock
for i, stock in enumerate(list_size):
print stock, i
完整修正后的代码示例
df = get_fundamentals(query(
valuation.code,
valuation.market_cap,
valuation.pb_ratio,
valuation.pe_ratio,
indicator.inc_return
).filter(
valuation.code.in_(context.universe),
valuation.pb_ratio > 0,
valuation.pe_ratio > 0,
indicator.inc_return > 0
)).dropna()
# 按市值排序
df_size = df.sort_values(by='market_cap') # 注意:新版 pandas 建议使用 sort_values
# 提取 code 列并转换为 Python list
list_size = df_size['code'].tolist()
# 遍历并打印股票代码及其在列表中的索引
for i, stock in enumerate(list_size):
print(stock, i)
总结:在处理 get_fundamentals 返回的 DataFrame 时,提取单列得到的是 Series,如果需要使用列表特有的方法,请务必先使用 .tolist() 进行类型转换。