在DataFrame iterrows中更改布尔值不会做任何事情

时间:2018-01-03 02:15:08

标签: python python-3.x pandas

一般的想法是:

  1. 从Excel中读取DataFrame
  2. 添加一个新列,我可以在其中标识有效行和无效行(在此示例中,值已在None初始化,但我也尝试在False0初始化
  3. 迭代DataFrame并根据一系列测试将值分配给新列。 (遗憾的是,测试过于复杂而无法使用applymap或类似的)
  4. 预期的结果是打印DataFrame并查看正确分配的新列的值。

    经验丰富的结果是价值根本没有改变。它们都保持初始值。

    这是一个高度简化的代码示例,其中存在行为。

    import pandas as pd
    
    df = pd.read_csv('./some_file.csv', sep='\t')
    
    print(df)   # View outputs below
    
    df['Valid'] = [None for _ in range(len(df))]    # New column
    
    for n in df.iterrows():
        if pd.notnull(n[1].Name):    # Example test
            n[1].Valid = False
        else:    # else clause should ensure all values change
            n[1].Valid = True
    
    print(df)    # Shows all df.Valid values are still None
    

    read_csv()

    后输出1
        Name  Age
    0   John   20
    1  Mandy   25
    2   Mike   30
    3    NaN   40
    4   Alex   35
    

    代码末尾的输出2:

        Name  Age Valid
    0   John   20  None
    1  Mandy   25  None
    2   Mike   30  None
    3    NaN   40  None
    4   Alex   35  None
    

    在上面的示例中,当打印df时,即使调试器显示进入赋值语句的进程,所有值仍为None

    是否存在我未见到的某种范围,参考或可变性问题?任何人都可以解释这种行为吗?

    运行python 3.6.0

    对于示例数据集,我手动构建了一个由制表符分隔的some_file.csv文件(第4行有一个空字符串用于Name,而年龄为40,第5行被read_csv跳过,原因很明显):

    Name    Age
    John    20
    Mandy   25
    Mike    30
        40
    
    Alex    35
    

1 个答案:

答案 0 :(得分:1)

Dataframe.iterrows()返回一个系列,它是数据的副本。它不能用于更新基础DataFrame。相反,我建议只需构建一个列表,并在完成后将其添加到Dataframe中:

测试代码:

import pandas as pd
df = pd.read_csv('input.csv', sep='\t')

valid = []
for n in df.iterrows():
    if pd.notnull(n[1].Name):    # Example test
        valid.append(False)
    else:    # else clause should ensure all values change
        valid.append(True)
df['Valid'] = valid    # New column

print(df)    # Shows all df.Valid values are still None

结果:

    Name  Age  Valid
0   John   20  False
1  Mandy   25  False
2   Mike   30  False
3    NaN   40   True
4   Alex   35  False