1
votes

Explosez une seule ligne de pandas dataframe en plusieurs lignes sur plusieurs colonnes simultanément

J'ai un dataframe df comme

desired_df
       col1 act_id col2                                                                                                 
       ---------------
    0  40   act1   A
    1  30   act1   B
    2  30   act1   C
    3  25   act2   D
    4  50   act2   E
    5  25   act2   F                                                                                                  
    6  70   act3   G                                                                              
    7  30   act3   H                                                                               

Je veux battre chaque record de telle manière que les valeurs de la colonne col1 et col2 explosent en plusieurs lignes, mais de telle sorte que la première valeur de col1 après le fractionnement sur ';' correspond à la première valeur de col2 après la séparation sur ';' . Donc, mon desired_df devrait ressembler à ceci:

df
       col1 act_id col2                                                                                                 
   --------------------
0  40;30;30   act1 A;B;C
1  25;50;25   act2 D;E;F
2     70;30   act3 G;H

REMARQUE: ce n'est pas la même chose que l' entrée de chaîne Split (exploser) pandas dataframe pour séparer les lignes, car ici l'explosion / la division d'un enregistrement ne se fait pas seulement sur une colonne, mais il est nécessaire de diviser ou d'exploser une ligne en plusieurs lignes, en deux colonnes simultanément.

Toute aide est appréciée. Merci


1 commentaires

vous pouvez utiliser unnesting(df,['col1','col2']) partir d'ici: stackoverflow.com/questions/53218931/… après avoir divisé les cols par ; comme df.col1=df.col1.str.split(';') et même pour col2


3 Réponses :


1
votes

une façon de faire cela

  col1 act_id col2
0  A    act1   40 
1  B    act1   30 
2  C    act1   30 
3  D    act2   25 
4  E    act2   50 
5  F    act2   25 
6  G    act3   70 
7  H    act3   30 

df2.set_index('act_id').apply(lambda x: pd.Series(x.col1.split(';'),x.col2.split(';')), axis=1).stack().dropna().reset_index()

df2.columns = ['col1','act_id','col2']


4 commentaires

cette solution a fonctionné pour ce df particulier, bien que lorsque j'ai essayé de l'exécuter sur une trame de données plus grande avec environ 1M de lignes, j'ai eu l'erreur ValueError: cannot reindex from a duplicate axis je ne comprends pas parce que même la plus grande trame de données d'origine avait juste ces Colonnes.


essayez la mise à jour ... le problème peut être lié à des valeurs d'index dupliquées, si la mise à jour ne fonctionne pas, essayez de casser le code et de l'exécuter étape par étape, cela vous aidera à déboguer le problème (postez sur quelle étape vous avez rencontré l'erreur)


J'ai essayé de le décomposer étape par étape et j'ai trouvé que l'erreur se produisait à la set_index('act_id') . J'ai supprimé toutes les autres méthodes et j'ai toujours l'erreur ValueError: cannot reindex from a duplicate axis Existe-t-il un autre moyen d'obtenir le résultat souhaité ...?


Je ValueError: cannot reindex from a duplicate axis toujours par avoir l'erreur ValueError: cannot reindex from a duplicate axis



0
votes

l'idée est col1 et col2 doit être éclaté, puis fusionner sur l'index et rejoindre le dataframe d'origine.

df1 = df.col1.str.split(";").apply(pd.Series).stack().droplevel(1).reset_index()
df2 = df.col2.str.split(";").apply(pd.Series).stack().droplevel(1).reset_index()
df12 = pd.merge(df1, df2[0], left_index=True, right_index=True)
df12.columns = ["index", "col1", "col2"]

pd.merge(df12, df["act_id"], left_on="index", right_index=True)


2 commentaires

AttributeError: 'Series' object has no attribute 'droplevel1'


droplevel(1) .



0
votes

Une fonction générique pourrait être:

list_cols = {'col1','col2'}
other_cols = list(set(df.columns) - set(list_cols))
exploded = [df[col].explode() for col in list_cols]
desired_df = pd.DataFrame(dict(zip(list_cols, exploded)))
desired_df = df[other_cols].merge(desired_df, how="right", left_index=True, right_index=True)

Veuillez strsplit les col 1 et 2 avant d'appeler la fonction ci-dessus


0 commentaires