1
votes

Quelle est la meilleure façon de supprimer tous les éléments d'un dataframe pandas où une valeur dans une colonne existe plus d'une fois dans une autre colonne?

J'ai un DataFrame composé de plusieurs arbres. Je souhaite supprimer toutes les lignes où le RootNode est présent plusieurs fois dans la colonne ToNode . Cependant, un nœud dans ToNode peut être présent plusieurs fois, s'il ne s'agit pas d'un nœud racine.

Voici un exemple du df.

root_list = list(df['Root'].unique())
for node in root_list:
  if len(df[df['ToNode'] == node]) > 1:
    df = df[df['Root'] != node]

Ici, je voudrais supprimer toutes les lignes où Root == A afin que le df résultant soit

ToNode | FromNode | Root  
  C        None      C 
  A         C        C  
  B         A        C    

Une approche (qui est très lent) pour y parvenir est le suivant:

ToNode | FromNode | Root
  A        None      A  
  B         A        A
  C        None      C 
  A         C        C  
  B         A        C

J'imagine qu'il existe un moyen beaucoup plus rapide, peut-être en utilisant groupby () et transform () et / ou map / apply.

Quelqu'un a-t-il des conseils pour rendre cela plus rapide? p >


2 commentaires

Ici, je voudrais supprimer toutes les lignes où Root == A afin que le df résultant soit essayez df = df.loc [df.loc [:, 'Root']! = 'A ',:]


Je ne veux pas simplement supprimer la racine "A", c'est un exemple. Je peux avoir 1000 valeurs Root différentes que je souhaite supprimer.


3 Réponses :


1
votes

recherchez d'abord tous les ToNode qui ont > 1 occurrence en utilisant groupby et filtrez df sur Root

    ToNode  FromNode    Root
2   C   None    C
3   A   C   C
4   B   A   C

qui vous donne le résultat suivant.

df2 = df.groupby(['ToNode'], as_index=False).count()
df[~df['Root'].isin(df2[df2['Root'] > 1]['ToNode'].unique())]


0 commentaires

1
votes

Vous pouvez essayer ce qui suit.

  • utilisez value_counts pour obtenir les décomptes
  • obtenir l'index où le nombre> = 2 satisfait
  • supprimez ces lignes.
>>> df.apply(pd.Series.value_counts, axis=1)[['A']] >= 2
       A
0   True
1   True
2  False
3  False
4  False

>>> mask = df.apply(pd.Series.value_counts, axis=1)[['A']] >= 2
>>> mask[mask.A].index
Int64Index([0, 1], dtype='int64')

>>> idx = mask[mask.A].index
>>> df.drop(idx)
  ToNode FromNode Root
2      C     None    C
3      A        C    C
4      B        A    C


0 commentaires

1
votes

Vous pouvez utiliser la Series .value_counts et Series.isin avec indexation booléenne. ~ ici est logique NOT:

  ToNode FromNode Root
2      C     None    C
3      A        C    C
4      B        A    C

[out

nodes_to_remove = df['ToNode'].value_counts()[lambda x: x > 1].index
#print(nodes_to_remove) Index(['A', 'B'], dtype='object')

df[~df['Root'].isin(nodes_to_remove)]


0 commentaires