4
votes

Supprimer une ligne d'un dataframe si ses valeurs de colonne se trouvent dans une autre

df1 = {
    'vouchers': [100, 300, 400],
    'units': [11, 12, 13],
    'some_other_data': ['a', 'c', 'd'],
    }

0 commentaires

6 Réponses :


3
votes

Faire avec merge indicateur , après avoir obtenu le index besoin de supprimer, en utilisant drop

idx=df1.merge(df2,on=['vouchers','units'],indicator=True,how='left').\
     loc[lambda x : x['_merge']=='both'].index
df1=df1.drop(idx,axis=0)
df1
Out[374]: 
   vouchers  units some_other_data
0       100     11               a
2       300     12               c
3       400     13               d


0 commentaires

5
votes

Vous pouvez le faire efficacement avec des opérations d'index, en utilisant pd.Index.isin:

u = df1.set_index(['vouchers', 'units'])
df1[~u.index.isin(pd.MultiIndex.from_arrays([df2.vouchers, df2.units]))]

   vouchers  units some_other_data
0       100     11               a
2       300     12               c
3       400     13               d


0 commentaires

0
votes

Ma solution:

df1 = {
    'vouchers': [100, 200, 300, 400],
    'units': [11, 12, 12, 13],
    'some_other_data': ['a', 'b', 'c', 'd']
    }
df2 = {
    'vouchers': [500, 200, 600, 300],
    'units': [11, 12, 12, 13],
    'some_other_data': ['a', 'b', 'c', 'd']
    }  

y = 0
for x in range(len(df1['vouchers'])):
    if df1['vouchers'][x-y] == df2['vouchers'][x]:
        if df1['units'][x-y] == df2['units'][x]:
            for key in df1.keys():
                del df1[key][x]
            y += 1


0 commentaires

1
votes

Une possibilité via pd.DataFrame .dupliqué :

df = pd.concat([df1, df2], ignore_index=True)
df = df.loc[~df.duplicated(subset=['vouchers', 'units'], keep=False)]
df = df.reindex(df.index & df1.index)

print(df)

#   some_other_data  units  vouchers
# 0               a     11       100
# 2               c     12       300
# 3               d     13       400


0 commentaires

0
votes

Essayez ceci, c'est simple:

excs = [] #will store the index of the values which are equal

for i, (key, value) in enumerate(zip(df1["vouchers"], df1["units"])):
  for key2, value2 in zip(df2["vouchers"], df2["units"]):
    if key == key2 and value == value2:
      excs.append(i)

for exc in excs:
  del(df1["vouchers"][exc])
  del(df1["units"][exc])


0 commentaires

2
votes

Bien que nous ayons beaucoup de bonnes réponses, mais les questions semblent intéressantes, donc comme l'apprentissage par conséquent, je l'admets dans un grand intérêt et je voudrais placer une autre version qui semble un peu plus simple en utilisant l'expression booléenne:

Premier DataFrame:

>>> df1[~df1.isin(df2).all(axis=1)]
   vouchers  units some_other_data
0       100     11               a
2       300     12               c
3       400     13               d

Deuxième DataFrame:

>>> df1.merge(df2, how='outer', indicator=True).query('_merge == "left_only"').drop('_merge', 1)
   vouchers  units some_other_data
0       100     11               a
2       300     12               c
3       400     13               d

Réponse possible plus simple:

>>> df1[(df1 != df2).any(1)]
   vouchers  units some_other_data
0       100     11               a
2       300     12               c
3       400     13               d

Solution 2: Utilisation de merge + indicateur code> + query

>>> df2
   vouchers  units some_other_data
0       500     11               a
1       200     12               b
2       600     12               c
3       300     13               d

Solution 3:

>>> df1
   vouchers  units some_other_data
0       100     11               a
1       200     12               b
2       300     12               c
3       400     13               d

p>


2 commentaires

J'aime vraiment la dernière solution pour la lisibilité, mais cela ne fonctionnera que si some_other_data est le même dans les deux dataframes. Pourrait-il être ajusté pour fonctionner même lorsque les données sont différentes? (Je vais également ajuster ma question)


@barciewicz, merci de l'aimer, mais la première réponse est plus robuste pour les données fournies, si vous l'aimez, vous pouvez toujours voter pour :-)