我正在尝试遍历数据框中的两列,并根据上述两个列值将1
或0
添加到新列。例如,如果列A是> B列然后将1
添加到C列。但是,我一直收到以下错误,我不确定原因。
ValueError: The truth value of a Series is ambiguous. Use a.empty,
a.bool(), a.item(), a.any() or a.all().
我的代码:
for i in df.itertuples():
if df['AdjClose'] > df['30ma']:
df['position'] = 1
elif df['AdjClose'] < df['30ma']:
df['position'] = 0
答案 0 :(得分:2)
你实际上并没有循环遍历这些行。在您的if语句中,您的条件不是True
或False
,而是系列。因此,错误。系列不是真或假,它是一个系列。编写代码的更正确方法是
for i in range(len(df)):
if df.loc[i, 'AdjClose'] > df.loc[i, '30ma']:
df.loc[i, 'position'] = 1
elif df.loc[i, 'AdjClose'] < df.loc[i, '30ma']:
df.loc[i, 'position'] = 0
编写代码的更短,更清洁,更多的熊猫式方法也有以下优势:
df.loc[df.AdjClose > df['30ma'], 'position'] = 1
df.loc[df.AdjClose < df['30ma'], 'position'] = 0
我强烈建议您阅读关于索引的文档,在开始使用pandas时可能会有些棘手。 https://pandas.pydata.org/pandas-docs/stable/indexing.html
编辑: 注意,for循环代码假设您的索引由0到n-1的唯一值组成。如果你有不同的索引,它会有点复杂。见https://pandas.pydata.org/pandas-docs/stable/whatsnew.html#deprecate-ix
答案 1 :(得分:1)
您的代码正在调用df.itertuples
,但未使用结果。您可以使用Ian Kent的建议或类似的东西来解决这个问题:
for row in df[['AdjClose', '30ma']].itertuples():
if row[1] > row[2]: # note: row[0] is the index value
df.loc[row.Index, 'position'] = 1
elif row[1] < row[2]:
df.loc[row.Index, 'position'] = 0
如果你的列都有名称是有效的Python标识符,你可以使用更整洁的东西:
for row in df.itertuples():
if row.AdjClose > row.ma30:
df.loc[row.Index, 'position'] = 1
elif row.AdjClose < row.ma30:
df.loc[row.Index, 'position'] = 0
请注意,如果df
的索引具有重复值,则这些都不起作用。
您也可以使用df.apply
,如下所示:
def pos(row):
if row['AdjClose'] > row['30ma']:
return 1
elif row['AdjClose'] > row['30ma']:
return 0
else:
return pd.np.nan # undefined?
df['position'] = df.apply(pos)
或只是
df['position'] = df.apply(lambda row: 1 if row['AdjClose'] > row['30ma'] else 0)
即使索引具有重复值,这也应该有效。但是,您必须为每一行定义一个值,甚至是row['AdjClose'] == row['30ma']
。
总的来说,你可能最喜欢Ian Kent的第二个推荐。
答案 2 :(得分:0)
你试图在多个值上测试一个布尔值(类似于if pd.Series([False, True, False])
,这不清楚结果是什么),所以pandas引发了这个错误。
该消息建议您可以使用any()
返回任何值(在本例中为您正在测试的值)True
。
所以也许是这样的:
for i in df.itertuples():
if (df['AdjClose'] > df['30ma']).any():
df['position'] = 1
elif (df['AdjClose'] < df['30ma']).any():
df['position'] = 0
有关详细信息,请参阅这些文档Using If/Truth Statements with pandas