Quiero deconstruir un DataFrame de pandas, usando encabezados de columna como una nueva columna de datos y crear una lista con todas las combinaciones del índice de fila y las columnas. Más fácil de mostrar que de explicar:
index_col = ["store1", "store2", "store3"] cols = ["January", "February", "March"] values = [[2,3,4],[5,6,7],[8,9,10]] df = pd.DataFrame(values, index=index_col, columns=cols)De este DataFrame deseo obtener la siguiente lista:
[['store1', 'January', 2], ['store1', 'February', 3], ['store1', 'March', 4], ['store2', 'January', 5], ['store2', 'February', 6], ['store2', 'March', 7], ['store3', 'January', 8], ['store3', 'February', 9], ['store3', 'March', 10]]¿Hay una manera conveniente de hacer esto?
La estructura en la que desea sus datos es muy desordenada, por lo que este es probablemente el mejor método dados los datos que desea.
# Results res = [] # Nested loop: first for length of index col, then next for cols for i in range(len(index_col)): for j in range(len(cols)): # Format of data res.append([index_col[i], cols[j], values[i][j]]) # Return results print(res) return resPuede iterar sobre los elementos del marco de datos usando
data = [] for col, row in df.items(): for ind, val in row.reset_index().values: data.append([ind, col, val]) dataPodría evitar el segundo bucle por sacrificar el orden en que solicitó la salida, ya que es un desglose completo de cómo comenzó la estructura.
df.unstack().swaplevel().reset_index().values.tolist() #OR df.reset_index().melt(id_vars="index").values.tolist() # [['store1', 'January', 2], # ['store2', 'January', 5], # ['store3', 'January', 8], # ['store1', 'February', 3], # ['store2', 'February', 6], # ['store3', 'February', 9], # ['store1', 'March', 4], # ['store2', 'March', 7], # ['store3', 'March', 10]]Con lo siguiente, el orden de los elementos coincidirá con el resultado de la pregunta.
df.transpose().unstack().reset_index().values.tolist() # [['store1', 'January', 2], # ['store1', 'February', 3], # ['store1', 'March', 4], # ['store2', 'January', 5], # ['store2', 'February', 6], # ['store2', 'March', 7], # ['store3', 'January', 8], # ['store3', 'February', 9], # ['store3', 'March', 10]]Verdadero estilo Pandas:
lst = [[*k, v] for k, v in df.unstack().swaplevel().to_dict().items()]temp = df.stack() [[*ent, val] for ent, val in zip(temp.index, temp)] [['store1', 'January', 2], ['store1', 'February', 3], ['store1', 'March', 4], ['store2', 'January', 5], ['store2', 'February', 6], ['store2', 'March', 7], ['store3', 'January', 8], ['store3', 'February', 9], ['store3', 'March', 10]]Preferiría apilar sobre desapilar y luego cambiar los niveles:
>>> df.stack().reset_index().to_numpy() array([['store1', 'January', 2], ['store1', 'February', 3], ['store1', 'March', 4], ['store2', 'January', 5], ['store2', 'February', 6], ['store2', 'March', 7], ['store3', 'January', 8], ['store3', 'February', 9], ['store3', 'March', 10]], dtype=object) >>> O con melt e ignore_index=False :
>>> df.melt(ignore_index=False).reset_index().to_numpy() array([['store1', 'January', 2], ['store2', 'January', 5], ['store3', 'January', 8], ['store1', 'February', 3], ['store2', 'February', 6], ['store3', 'February', 9], ['store1', 'March', 4], ['store2', 'March', 7], ['store3', 'March', 10]], dtype=object) >>>