Je dois en dessous de dataframe:
name item itemVal John item1 item1Val John item2 item2Val John item3 item3Val Tom item4 item4Val
Le dataframe est comme ceci:
name item itemVal John item1||item2||item3 item1Val||item2Val||item3Val Tom item4 item4Val
Je veux exploser la ligne en plusieurs lignes pour qu'elle soit comme ça (notez que l' item
et son itemVal
doivent correspondre).
import pandas as pd a = pd.DataFrame([{"name": "John", "item" : "item1||item2||item3", "itemVal" : "item1Val||item2Val||item3Val"}, {"name" : "Tom", "item":"item4", "itemVal" : "item4Val" } ])
J'ai regardé d'autres réponses ici:
Fractionner (exploser) l'entrée de chaîne de dataframe pandas pour séparer les lignes
pandas: Comment diviser le texte d'une colonne en plusieurs lignes?
Mais les travaux sur une seule colonne. Comment le faire fonctionner sur plusieurs colonnes? J'utilise Pandas 1.0.1 et Python 3.8
3 Réponses :
exploded = a[['item', 'itemVal']].apply(lambda x: [v.split('||') for v in x]).apply(pd.Series.explode) print( pd.concat([a['name'], exploded], axis=1) )
Merci pour votre solution, cela fonctionne. Cependant, existe-t-il un moyen de spécifier les seules colonnes que je souhaite fractionner?
Une combinaison de fermeture éclair , de produit et de chaîne peut réaliser la division en rangées. Comme cela implique des chaînes et, plus important encore, pas de calcul numérique, vous devriez obtenir des vitesses plus rapides en Python que de l'exécuter dans Pandas.
from itertools import product,chain combine = chain.from_iterable #pair item and itemval columns merge = zip(df.item,df.itemVal) #pair the entires from the splits of item and itemval merge = [zip(first.split("||"),last.split("||")) for first, last in merge] #create a cartesian product with the name column merger = [product([ent],cont) for ent, cont in zip(df.name,merge)] #create ur exploded values res = [(ent,*cont) for ent, cont in combine(merger)] pd.DataFrame(res,columns=['name','item','itemVal']) name item itemVal 0 John item1 item1Val 1 John item2 item2Val 2 John item3 item3Val 3 Tom item4 item4Val
Ce n'est peut-être pas aussi rapide que la réponse suggérée par Sammywemmy, mais voici une fonction générique qui fonctionne à l'aide des fonctions Pandas. Notez que la fonction d'éclatement ne fonctionne que sur une colonne à la fois. Donc:
df = pd.DataFrame({'A': [1, 2], 'B': [['a','b'], ['c','d']], 'C': [['z','y'], ['x','w']]}) A B C -------------- 1 [a, b] [z, y] 2 [c, d] [x, w] ##Logic for multi-col explode list_cols = {'B','C'} other_cols = list(set(df.columns) - set(list_cols)) exploded = [df[col].explode() for col in list_cols] df2 = pd.DataFrame(dict(zip(list_cols, exploded))) df2 = df[other_cols].merge(df2, how="right", left_index=True, right_index=True) A B C ------ 1 a z 1 b y 2 c x 2 d w
Est-ce toujours le cas que item et itemVal aient le même nombre de partitions?
@MichaelDelgado Oui toujours