pandas中.loc可提取列值但.at获取单个值报KeyError的解决方法
问题成因
- pandas的
.at是严格基于行列标签做精确匹配的单值索引器,不会做隐式的位置推断、类型转换,匹配规则比.loc更严格,只要传入的标签不存在就会直接抛KeyError。 - 这个报错的核心矛盾是:你打印
loc[:,"each"]看到的行号14,并不是rsiDFEach本身实际存在的行标签。出现这个认知差的原因很明确:- RSI指标计算规则决定了
length=14时,需要至少15条有效价格数据才能产出第一个非NaN值,也就是计算返回的Series长度至少15,索引从0到14。 - 你用来生成
rsiDFEach的原始数据prcAllExtractDF大概率之前做过行筛选、空值删除等操作但没有重置索引,导致rsiDFEach继承的行索引实际最大标签不到14;或者输入的价格序列本身长度不足15,pandas在给DataFrame赋值新列时按索引对齐自动截断了多余的计算结果,最终标签14根本没被写入rsiDFEach。
- RSI指标计算规则决定了
- 从报错栈可以看到异常出在
RangeIndex.get_loc方法,也印证了当前rsiDFEach的行索引是连续范围索引,14不在这个索引的合法取值范围内,你看到的打印输出是计算过程中临时Series的显示结果,不是最终DataFrame的真实索引。
解决方法
根据你的需求(提取单个值存入变量),选任意一种方案即可:
- 方案1:重置索引后再用
.at访问
先把DataFrame的索引重置为从0开始的连续整数,丢弃旧的无效索引,保证行标签和你看到的行号完全一致:def generateRSIDF(prcAllExtractDF: pd.DataFrame): rsiAllColumn = np.zeros(0) for i in range(0,1): rsiDFEach = prcAllExtractDF.iloc[:,i].to_frame() # 重置索引,丢弃原索引 rsiDFEach = rsiDFEach.reset_index(drop=True) rsiDFEach["each"] = pda.rsi(rsiDFEach.iloc[:,0], length=14) # 此时标签14真实存在,可正常访问 target_val = rsiDFEach.at[14, "each"] print(target_val) return rsiAllColumn - 方案2:用按位置索引的
.iat替代.at
不需要关心行标签具体是什么,直接按数据所在的行列位置提取,适合你明确知道要取第N行数据的场景:# 先获取"each"列的位置索引 each_col_idx = rsiDFEach.columns.get_loc("each") # 取第15行(位置索引从0开始,第15行对应位置14)的值 target_val = rsiDFEach.iat[14, each_col_idx] - 方案3:直接从RSI计算结果的Series中取值
把RSI计算结果存为临时变量,赋值给DataFrame列的同时直接从Series提取目标值,绕开DataFrame索引对齐的问题:def generateRSIDF(prcAllExtractDF: pd.DataFrame): rsiAllColumn = np.zeros(0) for i in range(0,1): price_series = prcAllExtractDF.iloc[:,i] rsi_series = pda.rsi(price_series, length=14) rsiDFEach = price_series.to_frame() rsiDFEach["each"] = rsi_series # 直接从计算好的RSI Series里取值 target_val = rsi_series.iloc[14] return rsiAllColumn - 方案4:用
.loc配合.item()提取标量
如果不想改原有索引逻辑,用.loc定位到目标单元格后,调用.item()直接转成原生Python类型的标量值,兼容性比.at更好:# 先通过索引位置取到实际的行标签,再访问 target_row_label = rsiDFEach.index[14] target_val = rsiDFEach.loc[target_row_label, "each"].item()
内容的提问来源于stack exchange,提问作者user19499906
相关产品推荐
相关产品推荐

