J'ai un pandas dataframe
qui contient une liste dans la colonne split_categories:
df[~(df['split_categories'].anyvalue.isin([480, 9, 104]))]
Je voudrais sélectionner toutes les lignes où la au moins une catégorie dans un liste spécifique [480, 9, 104].
Résultat attendu:
def match_categories(row): selected_categories = [480, 9, 104] result = [int(i) for i in row['split_categories'] if i in selected_categories] return result df['matched_categories'] = df.apply(match_categories, axis=1)
J'arrive à le faire en utilisant apply
:
album_id categories split_categories 0 66562 480.494 [480, 494] 3 1709 9 [9] 4 59239 105.104 [105, 104]
Mais ce code fonctionne en production et cela prend trop de temps (je l'exécute pour plusieurs colonnes contenant des listes)
Existe-t-il un moyen de l'exécuter quelque chose comme:
df.head() album_id categories split_categories 0 66562 480.494 [480, 494] 1 114582 128 [128] 2 4846 5 [5] 3 1709 9 [9] 4 59239 105.104 [105, 104]
Merci
5 Réponses :
Utilisation :
album_id categories split_categories 0 66562 480.494 [480, 494] 3 1709 9 [9] 4 59239 105.104 [105, 104]
Sortie :
print(df[~(df['split_categories'].isin([480, 9, 104])).any()])
Vous pouvez convertir chaque liste en ensembles, obtenir l'intersection et la convertir en booléen:
df = df[mask] print (df) album_id categories split_categories 0 66562 480.494 [480, 494] 3 1709 9 [9] 4 59239 105.104 [105, 104]
Ou convertir la colonne de liste
en DataFrame
, cast pour flotter et comparer avec isin
:
df1 = pd.DataFrame(df['split_categories'].values.tolist(), index=df.index) mask = df1.astype(float).isin(L).any(axis=1)
L = [480, 9, 104] mask = np.array([bool(set(map(int, x)) & set(L)) for x in df['split_categories']])
Vous pouvez développer la liste interne et vérifier si des éléments
dans les listes internes sont contenus dans [480, 9, 104]
:
l = [480, 9, 104] df[df.categories.str.split('.', expand=True).isin(map(str,l)).any(axis=1)] album_id categories split_categories 0 66562 480.494 [480,494] 3 1709 9.000 [9] 4 59239 105.104 [105,104]
df.split_categories.str.strip ('[]') renvoie un tableau de NaN (la valeur à l'intérieur de split_categories est déjà une liste (pas un trsing) J'ai utilisé df [df.categories.str.split ('.', expand = True) .isin (map (str, l)). Any (axis = 1)] à la place et cela a fonctionné. Merci
Ohh je vois, j'ai compris que vous deviez utiliser split_categories
à la place, j'ai mis à jour la réponse
Vous pouvez diviser en plusieurs séries numériques puis utiliser des opérations booléennes vectorisées. Les boucles au niveau Python utilisant des opérations par ligne sont généralement moins efficaces.
df = pd.DataFrame({'album_id': [66562, 114582, 4846, 1709, 59239], 'categories': ['480.494', '128', '5', '9', '105.104']}) split = df['categories'].str.split('.', expand=True).add_prefix('split_').astype(float) df = df.join(split) print(df) # album_id categories split_0 split_1 # 0 66562 480.494 480.0 494.0 # 1 114582 128 128.0 NaN # 2 4846 5 5.0 NaN # 3 1709 9 9.0 NaN # 4 59239 105.104 105.0 104.0 L = [480, 9, 104] res = df[df.filter(regex='^split_').isin(L).any(1)] print(res) # album_id categories split_0 split_1 # 0 66562 480.494 480.0 494.0 # 3 1709 9 9.0 NaN # 4 59239 105.104 105.0 104.0
Une autre méthode:
pat = '|'.join(r"\b{}\b".format(x) for x in my_list) df[df.split_categories.astype(str).str.contains(pat,na=False)] album_id categories split_categories 0 66562 480.494 [480, 494] 3 1709 9.000 [9] 4 59239 105.104 [105, 104]
Ou:
my_list = [480, 9, 104] pat = r'({})'.format('|'.join(str(i) for i in my_list)) #'(480|9|104)' <-- This is how the pat looks like df.loc[df.split_categories.astype(str).str.extract(pat, expand=False).dropna().index]
Cela fonctionnera à la fois avec split_categories
et Colonne catégories
.
str.contains ici c'est mieux
@jezrael j'avais essayé, j'ai reçu l'avertissement UserWarning: Ce modèle a des groupes de correspondance. Pour obtenir les groupes, utilisez str.extract.
:(
essayez pat = '|' .join (r "\ b {} \ b" .format (x) pour x dans L)
@jezrael qui fonctionne, merci. :) ajoutera dans edit. :) apprend encore le formatage des chaînes. :RÉ
Quelle est la taille maximale d'une liste dans
df ['split_categories']
, par exemple est-ce toujours 1 ou 2 éléments?