J'essaye de nettoyer un grand ensemble de données. Un échantillon de l'ensemble de données montre:

         Player Name        Headline    
0        LeBron James       Woj: NBA. ESPN planning for a H-O-R-S-E tourna...
1        LeBron James       LeBron James suggests 5-10 games before playoffs
2        LeBron James       LeBron James overcomes Pelicans with 34/13/12
3        LeBron James       Anthony Davis (knee) won't play on Sunday
...      ...                ...
105180   Ryan Anderson      Ryan Anderson has first career double-double
105181   Ryan Anderson      Yi says he'll be back after All-Star break
105182   Ryan Anderson      Anderson stays hot in Nets win

Le problème que je rencontre est que certains titres n'ont rien à voir avec le nom du joueur (comme vous pouvez le voir dans les lignes 0, 3 et 105181).

Question:

Existe-t-il un moyen de nettoyer les données afin qu'une partie de la colonne "Nom du joueur" figure dans la colonne "Titre"? Le reste qui ne correspond pas sera supprimé du nouvel ensemble de données créé.

Par exemple:

La ligne 0 serait supprimée car "LeBron" ou "James" ne se trouve pas dans la colonne "Titre".

Les rangées 1 et 2 resteraient les mêmes.

La ligne 3 serait supprimée car «LeBron» ou «James» ne se trouve pas dans la colonne «Titre».

La rangée 105180 resterait la même.

La ligne 105181 serait supprimée car «Ryan» ou «Anderson» ne se trouve pas dans la colonne «Headline».

La ligne 105182 resterait la même puisque «Anderson» est dans les colonnes «Player Name» et «Headline».

Le nouvel ensemble de données ne comportera que les données filtrées qui ont une partie de la colonne «Nom du joueur» dans la colonne «Titre». Je ne savais pas s'il y avait un moyen de faire cela ou si str.split devait être utilisé dans la colonne "Titre" pour séparer le nom du reste du titre, puis nettoyer à partir de là.

1
Sunny 3 juin 2020 à 01:47

4 réponses

Meilleure réponse

Vous pouvez utiliser split sur chaque cellule de la colonne Player Name et exécutez une vérification in pour chacun des mots séparés sur le Headline correspondant. Si any réussir le test in , gardez la ligne.

def any_words_included(x):
    return any(y in x["Headline"] for y in x["Player Name"].split())

df = df[df.apply(any_words_included, axis=1)]

Fournissez le kwarg axis=1 à { {X1}} pour filtrer sur les lignes.

1
ggorlen 2 juin 2020 à 23:22

Vous pouvez essayer ceci:

df['exists'] = df.apply(lambda x: any([k in x['Headline'] for k in x['Player Name'].split()]), axis=1)
df = df[~df['exists']==False].drop(columns=['exists'])
print(df)

Sortie:

     Player Name                                          Headline
1   LeBron James  LeBron James suggests 5-10 games before playoffs
2   LeBron James     LeBron James overcomes Pelicans with 34/13/12
4  Ryan Anderson      Ryan Anderson has first career double-double
6  Ryan Anderson                    Anderson stays hot in Nets win
2
NYC Coder 2 juin 2020 à 23:37

Vous pouvez écrire une fonction et l'appliquer à chaque ligne, comme ceci:

def keep_headlines(row):
    first = row['Player Name'].split()[0]
    last = row['Player Name'].split()[1]
    if (first in row['Headline']) | (last in row['Headline']):
        return 1 
    else:
        return 0

Vous pouvez ensuite appliquer cette fonction en utilisant la méthode apply:

df['mask'] = df.apply(keep_headlines, axis=1)
df = df[df['mask'] == 1]

Alors vous pouvez supprimer la colonne "masque".

df.drop(columns='mask', inplace=True)

J'espère que cette réponse vous aidera!

4
ashkan ghanavati 2 juin 2020 à 23:44

Vous pouvez utiliser groupby car vous semblez avoir plusieurs fois le même lecteur puis str.contains sur le nom du joueur une fois split pour obtenir l'une ou l'autre partie du nom.

df_ = df[df.groupby('Player Name')
           .apply(lambda x: x['Headline'].str.contains('|'.join(x.name.split(' '))))
           .reset_index(level=0, drop=True)]
print (df_)
          Player Name                                          Headline

1        LeBron James  LeBron James suggests 5-10 games before playoffs
2        LeBron James     LeBron James overcomes Pelicans with 34/13/12
105180  Ryan Anderson      Ryan Anderson has first career double-double
105182  Ryan Anderson                    Anderson stays hot in Nets win
0
Ben.T 3 juin 2020 à 00:05