Tengo una pregunta sobre la división de una lista en una columna de dataframe en varias filas.
Digamos que tengo este dataframe:
Job position Job type id 0 [6] [1] 3 1 [2, 6] [3, 6, 5] 4 2 [1] [9] 43
Me gustaría cada combinación de números, por lo que el resultado final sería:
id Job position Job type 0 3 6.0 1.0 1 4 2.0 3.0 2 4 2.0 6.0 3 4 2.0 5.0 4 4 6.0 3.0 5 4 6.0 6.0 6 4 6.0 5.0 7 43 1.0 9.0
Porque ahora mismo me sale este resultado:
id Job position Job type 0 3 6.0 1.0 1 4 2.0 3.0 2 4 6.0 6.0 3 4 NaN 5.0 4 43 1.0 9.0
Para obtener el resultado anterior, hice:
df = df.set_index(['id']) (df.apply(lambda x: pd.DataFrame(x.tolist(),index=x.index) .stack() .rename(x.name)).reset_index())
De manera similar a la sugerencia de Scott Boston, le sugiero que explote las columnas por separado y luego las combine.
Por ejemplo, para ‘Job position’:
>>> df['Job position'].apply(pd.Series).reset_index().melt(id_vars='index').dropna()[['index', 'value']].set_index('index') value index 0 6.0 1 2.0 2 1.0 1 6.0
Y, todos juntos:
df = pd.DataFrame({'Job position': [[6], [2, 6], [1]], 'Job type': [[1], [3, 6, 5], [9]], 'id': [3, 4, 43]}) jobs = df['Job position'].apply(pd.Series).reset_index().melt(id_vars='index').dropna()[['index', 'value']].set_index('index') types = df['Job type'].apply(pd.Series).reset_index().melt(id_vars='index').dropna()[['index', 'value']].set_index('index') >>> pd.merge( pd.merge( jobs, types, left_index=True, right_index=True), df[['id']], left_index=True, right_index=True).rename(columns={'value_x': 'Job positions', 'value_y': 'Job type'}) Job positions Job type id 0 6.0 1.0 3 1 2.0 3.0 4 1 2.0 6.0 4 1 2.0 5.0 4 1 6.0 3.0 4 1 6.0 6.0 4 1 6.0 5.0 4 2 1.0 9.0 43
Usa una comprensión
pd.DataFrame([ [p, t, i] for P, T, i in df.values for p in P for t in T ], columns=df.columns) Job position Job type id 0 6 1 3 1 2 3 4 2 2 6 4 3 2 5 4 4 6 3 4 5 6 6 4 6 6 5 4 7 1 9 43
Alternativas a la iteración sobre values
pd.DataFrame([ [p, t, i] for P, T, i in df.itertuples(index=False) for p in P for t in T ], columns=df.columns)
z = zip(df['Job position'], df['Job type'], df['id']) pd.DataFrame([ [p, t, i] for P, T, i in z for p in P for t in T ], columns=df.columns)
Para generalizar esta solución para acomodar cualquier número de columnas.
pd.DataFrame([ [p, t] + a for P, T, *a in df.values for p in P for t in T ], columns=df.columns) Job position Job type id 0 6 1 3 1 2 3 4 2 2 6 4 3 2 5 4 4 6 3 4 5 6 6 4 6 6 5 4 7 1 9 43
Desde el constructor del dataframe
s1=df.Jobposition.str.len() s2=df.Jobtype.str.len() pd.DataFrame({'id':df.id.repeat(s1*s2), 'Jobposition':np.concatenate([np.repeat(x,y) for x,y in zip(df.Jobposition,s2)]), 'Jobtype':np.concatenate(np.repeat(df.Jobtype,s1).values)}) Jobposition Jobtype id 0 6 1 3 1 2 3 4 1 2 6 4 1 2 5 4 1 6 3 4 1 6 6 4 1 6 5 4 2 1 9 43
import itertools dfres = pd.DataFrame([j+(i[2],) for i in df.values for j in itertools.product(*i[0:2])] ,columns=df.columns) Job position Job type id 0 6 1 3 1 2 3 4 2 2 6 4 3 2 5 4 4 6 3 4 5 6 6 4 6 6 5 4 7 1 9 43