J'ai une liste avec environ 90k chaînes et une trame de données avec plusieurs colonnes, je suis intéressé à vérifier si une chaîne de la liste est dans la colonne_1 et si elle attribue la même valeur à la colonne_2.

Je peux le faire:

for i in range(len(my_list)):
    item = list[i]
    for j in range(len(df)):
         if item == df['column_1'][j]:
             df['column_2'][j] = item

Mais je préfère éviter les boucles imbriquées

J'ai essayé

for item in my list:
    if item in list(df['column _1']):
          position = df[df['column_1']==item]].index.values[0]
          df['column_2'][position]  = item

Mais je pense que cette solution est encore plus lente et plus difficile à lire, cette opération peut-elle se faire avec une simple compréhension de liste?

Éditer.

La deuxième solution est beaucoup plus rapide, d'un ordre de grandeur environ. pourquoi donc? semble que dans ce cas, il doit rechercher deux fois le mach:

Ici:

if item in list(df['column _1'])

Et ici:

possition = df[df['column_1]=='tem]].index.values[0]

Je préférerais toujours une solution plus simple.

4
Luis Ramon Ramirez Rodriguez 7 mars 2016 à 17:04

4 réponses

Meilleure réponse

Vous pouvez le faire en divisant les actions de filtrage et d'affectation que vous avez décrites en deux étapes distinctes.

Les objets de la série Pandas incluent une méthode 'isin' qui pourrait vous permettre d'identifier les lignes dont les valeurs column_1 sont dans my_list et enregistre les résultats dans une série booléenne. Cela peut à son tour être utilisé avec la méthode d'indexation .loc pour copier les valeurs des lignes appropriées de la colonne 1 à la colonne 2

# Identify the matching rows
matches = df['column_1'].isin(my_list)
# Set the column_2 entries to column_1 in the matching rows
df.loc[matches,'column_2'] = df.loc[matches,'column_1']

Si column_2 n'existe pas déjà, cette approche crée column_2 et définit les valeurs non_matching sur NaN. La méthode .loc est utilisée pour éviter d'opérer sur une copie des données lors de l'exécution des opérations d'indexation.

3
res_edit 7 mars 2016 à 14:30

Disons que vous avez une liste:

l = ['foo', 'bar']

Et un DataFrame:

df = pd.DataFrame(['some', 'short', 'string', 'has', 'foo'], columns=['col1'])

Vous pouvez utiliser df.apply

df['col2'] = df.apply(lambda x: x['col1'] if x['col1'] in l else None, axis=1)

df
    col1    col2
0   some    None
1   short   None
2   string  None
3   has     None
4   foo     foo
2
Kevin 7 mars 2016 à 14:35

Essayez ce one-liner:

df.loc[(df['column_1'].isin(my_list)), 'column_2'] = df['column_1']

La différence avec la solution de @ res_edit est l'absence du second df.loc[] qui devrait fonctionner un peu plus vite ...

1
MaxU 6 mai 2017 à 18:57

Selon la sagesse conventionnelle, vous ne devriez pas utiliser une liste de compréhension des effets secondaires. Vous créeriez une liste (peut-être énorme) dont vous n'avez pas besoin, gaspillant des ressources et nuisant à la lisibilité.

https://codereview.stackexchange.com/questions/58050/is-it-pythonic-to-create-side-effect-inside-list-comprehension Est-ce Pythonic d'utiliser des compréhensions de liste pour juste des effets secondaires? Boucles Python vs listes de compréhension vs carte pour les effets secondaires (c'est-à-dire sans utiliser les valeurs de retour)

1
Community 23 mai 2017 à 12:02