J'ai un modèle de données avec trois colonnes (CUST_ID, TOPIC, VALUE)
result = pd.DataFrame({"CUST_ID":["C1", "C2", "C3"],
"TOPIC_a_VALUE":[10, np.nan, 5],
"TOPIC_b_VALUE":[15, 8, 20]})
Je souhaite regrouper par CUST_ID, transformer la colonne "TOPIC" en deux colonnes "TOPIC_a_VALUE" et "TOPIC_b_VALUE "
Je sais comment le faire par SQL, mais comment le faire par des pandas?
SELECT CUST_ID,
MAX(CASE WHEN TOPIC = "TOPIC1" THEN VALUE ELSE 0 END) AS TOPIC_a_VALUE
MAX(CASE WHEN TOPIC = "TOPIC2" THEN VALUE ELSE 0 END) AS TOPIC_b_VALUE
FROM TABLE
GROUP BY CUST_ID
Le résultat que je veux est ci-dessous, p >
data = pd.DataFrame({"CUST_ID":["C1", "C1", "C2", "C3", "C3"],
"TOPIC":["TOPIC1", "TOPIC2", "TOPIC2", "TOPIC1", "TOPIC2"],
"VALUE":[10, 15, 8, 5, 20]})
4 Réponses :
Votre requête n'a pas de sens en SQL. Je suppose que vous avez l'intention de quelque chose comme ceci:
SELECT CUST_ID,
MAX(CASE WHEN TOPIC = 'a' THEN VALUE ELSE 0 END) AS TOPIC_a_VALUE
MAX(CASE WHEN TOPIC = 'b' THEN VALUE ELSE 0 END) AS TOPIC_b_VALUE
FROM TABLE
GROUP BY CUST_ID;
Cela n'aide pas directement avec la solution Pandas, mais au moins la requête aura du sens.
Pense à @Gordon Linoff, j'oublie la fonction d'aggération.
IIUC vous avez besoin de quelque chose comme:
df=data.pivot_table(index=['CUST_ID','TOPIC'],columns=['TOPIC']).reset_index()
df.columns=[''.join(col) for col in df.columns.values]
df.loc[df.CUST_ID.duplicated(keep=False)]=df.loc[df.CUST_ID.duplicated(keep=False)].bfill()
df=df.drop_duplicates('CUST_ID')
df=df.drop([col for col in df.columns if 'Key' in col],axis=1).reset_index(drop=True)
print(df)
CUST_ID TOPIC VALUETOPIC1 VALUETOPIC2
0 C1 TOPIC1 10.0 15.0
1 C2 TOPIC2 NaN 8.0
2 C3 TOPIC1 5.0 20.0
Peut-être plus lisible que les autres réponses suggérées, j'irais avec:
.rename(columns={'TOPIC1': 'TOPIC_a_VALUE', 'TOPIC2': 'TOPIC_b_VALUE'})
Si vous préférez, vous pouvez bien sûr renommer les colonnes:
data.groupby(['CUST_ID', 'TOPIC'])['VALUE'].max().unstack() # Output #TOPIC TOPIC1 TOPIC2 #CUST_ID #C1 10.0 15.0 #C2 NaN 8.0 #C3 5.0 20.0
Oui, c'est mieux. Je ne pouvais pas penser à ça hier soir. +1
Vous pouvez utiliser groupby de la manière suivante:
df1 = df1.drop(columns = ['TOPIC']).
rename(columns{'VALUETOPIC1':'TOPIC_a_VALUE','VALUETOPIC2':'TOPIC_b_VALUE'})
Pour nettoyer le dataframe
df=data.pivot_table(index=['CUST_ID','TOPIC'],columns=['TOPIC']).reset_index()
df.columns=[''.join(col) for col in df.columns.values]
df1 = df.groupby('CUST_ID').ffill()\
.groupby('CUST_ID').last()\
.reset_index()
Pourriez-vous s'il vous plaît poster à quoi ressemble votre sortie finale en utilisant des données aléatoires
@Sumanth j'ajoute les données originales et le résultat par trame de données pandas
il n'y a pas de
TOPIC = "a"dans les données d'origine, veuillez l'ajouter afin que nous puissions répliquer@ anky_91 Je modifie la faute de frappe, merci