J'ai un dataframe pandas qui ressemble à ceci:
Item Status Value 123 B 1 123 BW 0 123 W 0 123 NF 0 456 W 0 456 BW 1 789 W 1 789 NF 0 000 NF 1
Et je dois créer une nouvelle colonne Value qui sera soit 1 ou 0 selon les valeurs dans les colonnes Item et Status . L'attribution de la valeur 1 est priorisée par cet ordre: B , BW , W , NF . Donc, en utilisant l'exemple de dataframe ci-dessus, le résultat devrait être:
Item Status 123 B 123 BW 123 W 123 NF 456 W 456 BW 789 W 789 NF 000 NF
Utilisation de Python 3.7.
3 Réponses :
Je pourrais peut-être vous aider sur le plan conceptuel, en vous expliquant certaines étapes que je ferais:
np.zeros () ou pd.fillna() groupby = pd.groupby ('Item') pour le nom, grouper dans groupby: En utilisant une fonction simple avec if, une file d'attente de priorité personnalisée, des critères de tri personnalisés ou toute autre méthode préférée, déterminez quelle entrée a la priorité la plus élevée " par cette valeur 1 est priorisé par cet ordre: B, BW, W, NF ", et attribuer une valeur de 1 à sa colonne Valeur group.loc [entrée] ['Valeur'] == 0
Disons que nous examinons le groupe "123":
Item Status Value ------------------------- 123 B 0 (before 0, after 1) 123 BW 0 123 W 0 123 NF 0
Étant donné que la ligne [123, 'B', 0] avait la priorité la plus élevée en fonction de vos critères, vous la remplacez par [123, 'B', 1] code >
Une fois terminé, recréez le dataframe à partir de l'objet groupby, et vous avez terminé. Vous avez beaucoup de possibilités pour le faire, peut-être vérifier ici: Conversion d'un Pandas GroupBy objecter à DataFrame
En prenant votre dataframe d'origine comme dataframe d'entrée df , le code suivant produira la sortie souhaitée:
#dictionary assigning order of priority to status values
priority_map = {'B':1,'BW':2,'W':3,'NF':4}
#new temporary column that converts Status values to order of priority values
df['rank'] = df['Status'].map(priority_map)
#create dictionary with Item as key and lowest rank value per Item as value
lowest_val_dict = df.groupby('Item')['rank'].min().to_dict()
#new column that assigns the same Value to all rows per Item
df['Value'] = df['Item'].map(lowest_val_dict)
#replace Values where rank is different with 0's
df['Value'] = np.where(df['Value'] == df['rank'],1,0)
#delete rank column
del df['rank']
Je préférerais une approche où le statut est un ordre pd.Categorical , car a) c'est ce que c'est et b) c'est beaucoup plus lisible: si vous avez cela, vous comparez simplement si une valeur est égale au max de son groupe:
df['Status'] = pd.Categorical(df['Status'], categories=['NF', 'W', 'BW', 'B'],
ordered=True)
df['Value'] = df.groupby('Item')['Status'].apply(lambda x: (x == x.max()).astype(int))
# Item Status Value
#0 123 B 1
#1 123 BW 0
#2 123 W 0
#3 123 NF 0
#4 456 W 0
#5 456 BW 1
#6 789 W 1
#7 789 NF 0
#8 0 NF 1
Le dernier devrait être meilleur par df ['Value'] = df.groupby ('Item') ['Status']. Transform ('max'). Eq (df ['Status']). Astype ( int)
Vous pourriez le considérer mieux, car il est un peu plus rapide pour les très grandes trames de données, même si je dirais qu'il est moins lisible. Bref, bon commentaire, approche intéressante
Comment la colonne
Itemjoue-t-elle un rôle à cet égard? Attribuez-vous une seule valeur1parArticle, en fonction de l’ordre de priorité dansStatut?S'il n'y a qu'une seule instance d'un certain élément dans la colonne
Item, elle doit être1par défaut. Cependant, lorsqu'il y a plus d'une occurrence d'un élément, alors, en fonction duStatutet de la priorité, il doit y avoir une valeur correspondante de1ou0. J'espère que cela a du sens.