Python:循环中对 IF 语句的不一致处理

Posted

技术标签:

【中文标题】Python:循环中对 IF 语句的不一致处理【英文标题】:Python: inconsistent handling of IF statement in loop 【发布时间】:2020-12-24 16:09:34 【问题描述】:

我有一个包含条件和值的数据框df

import pandas as pd
df=pd.DataFrame('COND':['X','X','X','Y','Y','Y'], 'VALUE':[1,2,3,1,2,3])

因此df 看起来像:

  COND  VALUE
     X      1
     X      2
     X      3
     Y      1
     Y      2
     Y      3

我正在使用循环根据CONDdf 进行子集化,并编写包含每个条件值的单独文本文件

conditions = 'X','Y'
for condition in conditions:
    df2 = df[df['COND'].isin([condition])][['VALUE']]
    df2.to_csv(condition + '_values.txt', header=False, index=False)

最终结果是两个文本文件:X_vals.txt 和 Y_vals.txt,这两个文件都包含1 2 3。到目前为止,一切都按预期工作。

我想进一步子集df 仅用于一个条件。例如,也许我想要条件 Y 中的所有值,但只有条件 X 中的值 1 2,而 Y_vals.txt 应该包含 1 2 3。我尝试使用 IF 语句来实现这一点:

conditions = 'X','Y'
for condition in conditions:
    if condition == 'X':
        df = df[df['VALUE'] < 3]

    df2 = df[df['COND'].isin([condition])][['VALUE']]
    df2.to_csv(condition + '_values.txt', header=False, index=False)

这就是不一致发生的地方。上面的代码工作正常(即 X_vals.txt 包含1 2,和 Y_vals.txt 1 2 3,正如预期的那样),但是当我使用if condition=='Y' 而不是if condition=='X' 时,它会中断,并且两个文本文件都只包含@ 987654337@.

换句话说,如果我在 IF 语句中指定 conditions 的第一个元素,那么它会按预期工作,但是如果我指定第二个元素,那么它会中断并将

这是怎么回事,我该如何解决?

谢谢!

【问题讨论】:

df = df[df['VALUE'] &lt; 3] 您在循环中更改了初始数据框 - 那是您的错误 【参考方案1】:

您遇到的问题是因为您在循环内覆盖了df

conditions = 'X','Y'
for condition in conditions:
    if condition == 'X':
        df = df[df['VALUE'] < 3]  # <-- HERE'S YOUR ISSUE

    df2 = df[df['COND'].isin([condition])][['VALUE']]
    df2.to_csv(condition + '_values.txt', header=False, index=False)

让我有点惊讶的是,当你循环遍历集合 conditions 时,你首先得到 condition = 'Y'然后 condition = 'X'。但是作为一个集合是一个无序集合(即它没有声称它的元素具有固有的顺序),这不应该太令人不安:python 只是读取元素的最内部方便的方式。

您可以使用conditions = ['X', 'Y'] 来循环遍历列表(有序集合)。然后它将先执行 X,然后执行 Y。但是,如果您这样做,您将得到相同的错误,但相反(即它适用于 if condition == 'Y',但不适用于 if condition == 'X')。

这是因为循环运行一次后,df 已重新分配给原始 df 的子集,该子集仅包含小于 3 的值。这就是为什么如果if condition 语句在第一次通过循环时触发,那么您在两个文件中都只能得到值 1 和 2。

现在进行修复:


conditions = ['X', 'Y']

for condition in conditions:

    csv_name = f"condition_values.txt"

    if condition == 'X':
        df_filter = f"VALUE < 3 & COND == 'condition'"
    else:
        df_filter = f"COND == 'condition'"

    df.query(df_filter).VALUE.to_csv(csv_name, header=False, index=False)

在这里我介绍了DataFrame.query 方法,它通常比尝试创建一个布尔系列用作掩码更简洁。

f-string 语法仅适用于 python 3.6+,如果您使用的是较低版本,请酌情修改(例如df_filter = "COND == ''".format(condition)

【讨论】:

感谢您的详尽回答!您能否说明如何使用 f-string 适应每行的较低版本? 这就是我最后一行示例的意思。格式化字符串有多种方法,但其中一种方法是字符串的format 方法。在每种情况下,只需删除 f 前缀并将 .format(condition=condition) 放在字符串的末尾。或者,为简洁起见,.format(condition) 并将 condition 更改为 ,如我的示例所示。【参考方案2】:
df=pd.DataFrame('COND':['X','X','X','Y','Y','Y'], 'VALUE':[1,2,3,1,2,3])

conditions = df.COND

for condition in conditions:
 print(condition)
 df2=df[df['COND'].isin([condition])][['VALUE']]
 df2.to_csv(condition + '_values.txt',header=False, index=False)


for condition in conditions:
 if condition=='X':
     df=df[df['VALUE'] < 3]

 df2=df[df['COND'].isin([condition])][['VALUE']]
 df2.to_csv(condition + '_values.txt',header=False, index=False)

您没有指定变量“条件”,所以它给了您一个错误。 尝试做:

条件 = df.COND

在for循环之前

【讨论】:

糟糕 - 我最初将条件定义为 conditions='X','Y' (已编辑以包含此内容)但您的回答揭示了一些新的东西。使用 conditions='X','Y' 定义条件会导致我描述的问题,但是按照您的建议使用 conditions=df.COND 会导致代码每次都失败 - 也就是说,无论如何,所有 df 总是被子集化我在 IF 语句中使用哪个条件。有趣...【参考方案3】:

我们可以将条件写入dict,然后使用map过滤groupby之前的df

cond = 'X' : 2, 'Y' : 3
subdf = df[df['VALUE']<df.COND.map(cond)]
for x, y in subdf.groupby('COND'):
    y.to_csv(x + '_values.txt')

【讨论】:

感谢您提供此解决方法,但是我真的想了解现有代码有什么问题。我正在使用一个脚本,它使用我上面描述的更复杂的版本,所以我需要知道这里出了什么问题

以上是关于Python:循环中对 IF 语句的不一致处理的主要内容,如果未能解决你的问题,请参考以下文章

如何在while循环中处理if语句 - Python

Python循环

第二节 Python基础之变量,运算符,if语句,while和for循环语句

循环语句中while(1)中的1是啥意思

Python学习杂记_4_分支和循环

Python循环