首页 > 解决方案 > 更新重复项的更快方法

问题描述

我的目标是更新一列重复项,但只更新第二个+(第一个应该保持不变),例如:

df_example:

    Name    val1     val2     val3   
0   AAA     11        3        1
1   AAA     22        3        1
2   BBB     33        2        2
3   CCC     44        3        3
4   DDD     55        2        4
5   DDD     66        2        4
6   DDD     77        3        4

预期的输出将是:

    Name  val1   val2     val3   
0   AAA    11    3        1
1   AAA    22    3        0
2   BBB    33    2        2
3   CCC    44    3        3
4   DDD    55    2        4
5   DDD    66    2        0
6   DDD    77    3        4  ( unchanged because Val2 is different ) 

我目前正在使用 iterrows (我知道这是最糟糕的选择,但我找不到更好的选择):

list = []
for index, row in df.iterrows():

    if (row['Name']+row['val2'] in list):            # Check for Name + Val2
        row['val3'] = '0'                             
    list.append(row['Name']+row['val2'])    # Inserts the new Name+Val2 in the list , next time 
                                                 #this combination appears will fall in the if statement

对于不那么小的数据集(~ 1MM 行),这需要大约 20 分钟......这太多了

谢谢,

标签: pythonpandas

解决方案


您可以使用df[['Name', 'val2']].duplicated()创建一系列bools 来确定组合是否已经存在。然后我们可以使用该掩码来设置 val3` 列的值:

df.loc[df[['Name', 'val2']].duplicated(), 'val3'] = 0

对于给定的样本数据,这给了我们:

>>> df = pd.DataFrame({'Name': ['AAA', 'AAA', 'BBB', 'CCC', 'DDD', 'DDD', 'DDD'], 'val1': [11,22,33,44,55,66,77], 'val2': [3,3,2,3,2,2,3], 'val3': [1,1,2,3,4,4,4]})
>>> df
  Name  val1  val2  val3
0  AAA    11     3     1
1  AAA    22     3     1
2  BBB    33     2     2
3  CCC    44     3     3
4  DDD    55     2     4
5  DDD    66     2     4
6  DDD    77     3     4
>>> df.loc[df[['Name', 'val2']].duplicated(), 'val3'] = 0
>>> df
  Name  val1  val2  val3
0  AAA    11     3     1
1  AAA    22     3     0
2  BBB    33     2     2
3  CCC    44     3     3
4  DDD    55     2     4
5  DDD    66     2     0
6  DDD    77     3     4

如果我们重复样本数据帧中的记录数 200'000 次,并且我们运行上述的一百次,我们将获得以下基准:

>>> df = pd.DataFrame({'Name': ['AAA', 'AAA', 'BBB', 'CCC', 'DDD', 'DDD', 'DDD']*200000, 'val1': [11,22,33,44,55,66,77]*200000, 'val2': [3,3,2,3,2,2,3]*200000, 'val3': [1,1,2,3,4,4,4]*200000})
>>> def f():
...     df.loc[df[['Name', 'val2']].duplicated(), 'val3'] = 0
... 
>>> from timeit import timeit
>>> timeit(f, number=100)
11.420697326015215

对于一个有 140 万行的数据帧,我们可以平均在 0.1142 秒内完成处理。


推荐阅读