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