为什么我在pandas datafram中循环时收到这个错误

2024-04-18 17:29:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在dataframe中的两个列中循环,并基于上述两个列值将1或{}添加到新列中。例如,如果列A是列B,那么将A 1添加到C列中。在

ValueError: The truth value of a Series is ambiguous. Use a.empty, 
a.bool(), a.item(), a.any() or a.all().

我的代码:

^{pr2}$

Tags: ofthedataframeisvalueuseanyitem
3条回答

您尝试在多个值上测试一个布尔值(类似于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

实际上,您并没有在行中循环。在if语句中,条件不是True或{},而是一个序列。因此,错误。系列不是真是假,它是一个系列。编写代码的更正确的方法是

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

一种更短、更干净、更熊猫式的编写代码的方法是:

^{pr2}$

我强烈推荐阅读关于索引的文档,在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

您的代码正在调用df.itertuples,但没有使用结果。你可以用伊恩·肯特的建议来解决这个问题,或者类似这样的问题:

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标识符,则可以使用更简洁的名称:

^{pr2}$

请注意,如果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']的行。

总的来说,你最好接受伊恩肯特的第二次推荐。

相关问题 更多 >