猿问

如果某些行值与第二个 DataFrame 中的行值相同,则有效地从 DataFrame 中删除行

import pandas as pd


df1 = pd.DataFrame({'id':   [ 1,  1,  1,  2,  2,  2,  3,  3,  3], 

                    'nr':   [91, 92, 93, 91, 92, 93, 91, 92, 93], 

                    'val_a':[22, 23, 24, 33, 34, 35, 44, 43, 42]})


df2 = pd.DataFrame({'id':   [ 1,  1,  2,  3,  4,  4,  3,  5], 

                    'nr':   [91, 92, 91, 99, 92, 93, 92, 99], 

                    'val_a':[72, 27, 74, 83, 84, 85, 84, 83]})


def eliminate1 (): 

    for i1, row1 in df1.iterrows():

        for i2, row2 in df2.iterrows():

            if row1['id'] == row2['id'] and row1['nr'] == row2['nr']:

                df1.drop(i1, inplace=True)

    df1.reset_index(drop=True, inplace=True)

    print(df1)


eliminate1()

我想删除 df1 中的所有行,其中 'id' AND 'nr' 在 df2 的任何行中具有相等的值。消除1()效果很好,见下面的结果,但在大数据集的情况下非常慢。


这是 df1 和 df2:


   id  nr  val_a

0   1  91     22

1   1  92     23

2   1  93     24

3   2  91     33

4   2  92     34

5   2  93     35

6   3  91     44

7   3  92     43

8   3  93     42 


   id  nr  val_a

0   1  91     72

1   1  92     27

2   2  91     74

3   3  99     83

4   4  92     84

5   4  93     85

6   3  92     84

7   5  99     83 

这里的结果应该是这样的:


   id  nr  val_a

0   1  93     24

1   2  92     34

2   2  93     35

3   3  91     44

4   3  93     42

有谁知道如何编写更快的代码和/或使用已经存在的函数?


幕布斯6054654
浏览 264回答 3
3回答

郎朗坤

merge您可以merge使用indicator=True并仅包含标记为 的那些行'left_only'。res = df1.merge(df2.drop('val_a', 1), how='left', on=['id', 'nr'], indicator=True)res = res.loc[res['_merge'] == 'left_only'].drop('_merge', 1)print(res)   id  nr  val_a2   1  93     244   2  92     345   2  93     356   3  91     448   3  93     42该解决方案很容易适应任何条件,具体取决于'left_only'、'right_only'或'both'。

猛跑小猪

isin将merge列压缩后的方法1tupledf1[~df1[['id','nr']].apply(tuple,1).isin(df2[['id','nr']].apply(tuple,1))]Out[43]:    id  nr  val_a2   1  93     244   2  92     345   2  93     356   3  91     448   3  93     42方法二numpy广播s1=df1[['id','nr']].valuess2=df2[['id','nr']].valuesdf1[~np.any(np.all(s1==s2[:,None],-1),0)]Out[64]:    id  nr  val_a2   1  93     244   2  92     345   2  93     356   3  91     448   3  93     42我的方法计时%timeit df1[~df1[['id','nr']].apply(tuple,1).isin(df2[['id','nr']].apply(tuple,1))]100 loops, best of 3: 3.67 ms per loopdef m2():    s1 = df1[['id', 'nr']].values    s2 = df2[['id', 'nr']].values    return df1[~np.any(np.all(s1 == s2[:, None], -1), 0)]%timeit m2()1000 loops, best of 3: 926 µs per loop

aluckdog

能inner join解决你的问题吗?获取与条件匹配的参数的索引,然后将其过滤掉。reset_index()如果你想这样做,你只需要事后去做。df3 = df1.merge(df2, how = 'inner', on = ['id','nr']).reset_index()id_list = df3['id'].tolist()df4 = df1[~df1['id'].isin(id_list)]
随时随地看视频慕课网APP

相关分类

Python
我要回答