Lya*_*yam 3 python loops if-statement pandas
我有一个df
包含条件和值的数据框。
import pandas as pd
df=pd.DataFrame({'COND':['X','X','X','Y','Y','Y'], 'VALUE':[1,2,3,1,2,3]})
Run Code Online (Sandbox Code Playgroud)
因此df
看起来像:
COND VALUE
X 1
X 2
X 3
Y 1
Y 2
Y 3
Run Code Online (Sandbox Code Playgroud)
我正在使用循环来df
根据进行子集化COND
,并编写包含每个条件值的单独文本文件
conditions = {'X','Y'}
for condition in conditions:
df2 = df[df['COND'].isin([condition])][['VALUE']]
df2.to_csv(condition + '_values.txt', header=False, index=False)
Run Code Online (Sandbox Code Playgroud)
最终结果是两个文本文件:X_vals.txt 和 Y_vals.txt,它们都包含1 2 3
. 到目前为止,一切都按预期工作。
我只想df
为一个条件进一步子集。例如,也许我想要来自条件 Y 的所有值,但仅来自条件 X 的值 < 3。在这种情况下, X_vals.txt 应包含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)
Run Code Online (Sandbox Code Playgroud)
这就是不一致的地方。上面的代码工作正常(即 X_vals.txt 包含1 2
, 和 Y_vals.txt 1 2 3
,正如预期的那样),但是当我使用if condition=='Y'
代替 时if condition=='X'
,它会中断,并且两个文本文件都只包含1 2
.
换句话说,如果我conditions
在 IF 语句中指定了第一个元素,那么它会按预期工作,但是如果我指定第二个元素,那么它会中断并将 < 3 子集应用于来自两个条件的值。
这里发生了什么,我该如何解决?
谢谢!
您遇到的问题是因为您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)
Run Code Online (Sandbox Code Playgroud)
让我有点惊讶的是,当你循环遍历集合时,conditions
你condition = 'Y'
首先得到,然后 condition = 'X'
. 但是由于集合是一个无序的集合(即它不声称其元素具有固有的顺序),这不应该太令人不安:python 只是以最内部方便的方式读出元素。
您可以使用conditions = ['X', 'Y']
循环遍历列表(有序集合)。然后它会先做 X,然后是 Y。但是,如果你这样做,你会得到同样的错误,但反过来(即它适用于if condition == 'Y'
但不适用if condition == 'X'
)。
这是因为在循环运行一次之后,df
已经被重新分配给了原来df
只包含小于三个值的子集。这就是为什么如果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)
Run Code Online (Sandbox Code Playgroud)
在这里,我介绍了该DataFrame.query
方法,该方法通常比尝试创建布尔系列用作掩码更简洁,就像您所做的那样。
f-string 语法仅适用于 python 3.6+,如果您使用的是较低版本,则根据需要进行修改(例如df_filter = "COND == '{}'".format(condition)
)