J'ai une trame de données qui ressemble à ceci:

# df

colA     colB          colC

rqp      129            a   
pot      217;345        u
ghay     716            b
rbba     217;345        d
tary     612;811;760    a
kals     716            t

La combinaison ColB (n'importe quel composant sur deux illustré) et ColC forment une combinaison unique. Je veux créer un dataframe à partir de ce dataframe qui ressemblera à ce qui suit

# newdf:

colAA      coLBB      

(129,a)    (a,rqp)
(217,u)    (u,pot)
(345,u)    (u,pot)
(716,b)    (b,ghay)
(217,d)    (d,rbba)
(345,d)    (d,rbba)
(612,a)    (a,tary)
(811,a)    (a,tary)
(760,a)    (a,tary)
(716,t)    (t,kals)

J'ai essayé de créer de nouvelles colonnes s'il y a un seul élément dans colB, mais je ne peux pas savoir comment faire en utilisant le séparateur de point-virgule, puis comment créer des colonnes de tuples.

Si je n'ai pas de point-virgule dans ColB, je peux utiliser

df['AA'] = list(zip(df[colB], df[colC]))
df['AB'] = list(zip(df[colC], df[colA]))

Cependant, la présence d'un point-virgule dans ColB me pose des problèmes, comme la façon de diviser cette chaîne en plusieurs et d'attribuer les tuples. Toute aide sera très appréciée.

4
Stan 3 juin 2020 à 07:26

3 réponses

Meilleure réponse

Code

def merge(row):
    return pd.Series({
            "colAA": (row.colB, row.colC),
            "colBB": (row.colC, row.colA),
        })

df['colB'] = df['colB'].str.split(';')
df = df.explode('colB')
newDf = df.apply(merge, axis=1).reset_index(drop=True)

Explication

Vous pouvez split colB pour obtenir la liste des valeurs, Ensuite, appliquez la fonction explode pour obtenir plusieurs lignes

df['colB'] = df['colB'].str.split(';')
df = df.explode('colB')

# output
    colA    colB    colC
0   rqp 129 a
1   pot 217 u
1   pot 345 u
2   ghay    716 b
3   rbba    217 d

Ensuite, appliquez la fonction de fusion ci-dessous pour créer une nouvelle trame de données

def merge(row):
    for b in row.colB.split(";"):
         return pd.Series({
            "colAA": (b, row.colC),
            "colBB": (row.colC, row.colA),

        })

Appliquez ensuite cette fonction sur Df

newDf = df.apply(merge, axis=1).reset_index(drop=True)

# output
    colAA        colBB
0   (129, a)    (a, rqp)
1   (217, u)    (u, pot)
2   (345, u)    (u, pot)
3   (716, b)    (b, ghay)
4   (217, d)    (d, rbba)
5   (345, d)    (d, rbba)
6   (612, a)    (a, tary)
7   (811, a)    (a, tary)
8   (760, a)    (a, tary)
9   (716, t)    (t, kals)
0
Anurag Wagh 3 juin 2020 à 05:16

Vous pouvez simplement utiliser str.split() avec des paramètres d'expansion pour diviser la liste et obtenir de nouvelles colonnes en fonction de la division.

df['colB'].str.split(pat=';',expand=True)

En savoir plus ici

0
EXODIA 3 juin 2020 à 05:07

Utilisez, Series.str.split pour diviser les chaînes de la colonne colB autour du délimiteur ; puis en utilisant DataFrame.explode transforme chaque élément d'une colonne colB en une ligne, répliquant les valeurs d'index. Puis utilisez DataFrame.agg pour agréger les colonnes requises comme tuple le long de axis=1:

df['colB'] = df['colB'].str.split(';')
df = df.explode('colB')
df['ColAA'] = df[['colB', 'colC']].agg(tuple, axis=1)
df['ColBB'] = df[['colC', 'colA']].agg(tuple, axis=1)
df = df[['ColAA', 'ColBB']].reset_index(drop=True)

Résultat:

# print(df)
     ColAA      ColBB
0  (129, a)   (a, rqp)
1  (217, u)   (u, pot)
2  (345, u)   (u, pot)
3  (716, b)  (b, ghay)
4  (217, d)  (d, rbba)
5  (345, d)  (d, rbba)
6  (612, a)  (a, tary)
7  (811, a)  (a, tary)
8  (760, a)  (a, tary)
9  (716, t)  (t, kals)
2
Shubham Sharma 3 juin 2020 à 05:10