首页 > 解决方案 > “你永远不应该修改你正在迭代的东西”。那我该如何修改呢?

问题描述

我在这里阅读了Pandas 文档和许多评论,你不应该修改你正在迭代的东西。

假设我有这个dataframe

mydf = pd.DataFrame({'name':['jim','john','mary','michael'],
                    'age':[12,46,44,32]})

      name  age
0      jim   12
1     john   46
2     mary   44
3  michael   32

我想做以下事情:

1.如果名称以 开头j,则添加'smith'到名称中。

2.如果年龄大于 40,则乘以 2。

所以我创建了一个函数来做到这一点:

def modify(df):

    for i in range(len(df)):

        # if age is >40
        if df.loc[i,'age'] > 40:

            # multiply it by 2
            df.loc[i,'age'] = df.loc[i,'age']*2

        # get the name
        name = df.loc[i,'name']

        # if it starts with 'j'
        if name[0]=='j':

            # add 'smith' to the name
            name = name+' '+'smith'

        # insert into cell    
        df.loc[i,'name'] = name

应用功能:

modify(mydf)

结果:

print(mydf)

         name  age
0   jim smith   12
1  john smith   92
2        mary   88
3     michael   32

这工作得很好。所以有什么问题?

我应该复制数据框并在最后返回吗?如下所示:

def modify(df):

    df = df.copy()

    for i in range(len(df)):

        if df.loc[i,'age'] > 40:

            df.loc[i,'age'] = df.loc[i,'age']*2

        name = df.loc[i,'name']

        if name[0]=='j':

            name = name+' '+'smith'

        df.loc[i,'name'] = name

    return df

但是,我仍在编辑我正在迭代的内容。所以我想这仍然很糟糕?

注意:我正在开发一个比这更大、更复杂的函数,它有更多的条件和 api 调用等,它会遍历 100,000 行客户数据。例如,如果客户来自 X 市do this,如果客户来自 Y 市,do that等等。所以我不是在寻找这个确切数据框的解决方案。

我只想知道如果您必须在完全不推荐的情况下迭代和编辑行时该怎么办。

标签: pythonpandas

解决方案


for使用pandas. pandas代表优化这些循环。

这是解决您的问题的代码:

idx_smith = mydf[mydf["name"].str.startswith("j")].index
idx_age = mydf[mydf["age"] > 40].index
mydf.loc[idx_smith, "name"] = mydf.loc[idx_smith].name + " smith"
mydf.loc[idx_age, "age"] = mydf.loc[idx_age].age*2

mydf

    name    age
0   jim smith   12
1   john smith  92
2   mary    88
3   michael 32

对您的问题的回答:您应该使用迭代来进行行操作pandas 适用于 lambda以提高内存/cpu 使用率。


推荐阅读