Si tiene un objeto ordenado de la serie pandas con índices únicos, el uso de pd.Series.to_dict () funciona como es de esperar: se convierte en un dict Python con cada índice apuntando a su valor respectivo.

Esto se complica si tiene índices no únicos. Mi comportamiento esperado es que los valores con el mismo índice se agruparán en una lista, y el dict tendrá el índice como una clave y la lista como un valor. Lo que observo en cambio es un dict con el índice como clave y solo un valor único de la serie como el valor en el dict.

¿Hay alguna manera de lograr mi comportamiento esperado, integrado en los pandas o cerca de él? Actualmente, selecciono manualmente los valores que coinciden con cada índice en el dict en un bucle for, haciendo un bucle sobre los valores de índice únicos. ¿Hay una mejor manera de hacer esto?

EDITAR: Aquí hay un ejemplo:

my_series = pd.Series(['val_1', 'val_2', 'val_3', 'val_4', 'val_5'])
my_series.index = ['1', '1', '2', '2', '2']
my_series

Rendimientos

1    val_1
1    val_2
2    val_3
2    val_4
2    val_5
dtype: object

Ahora, to_dict () con el comportamiento de coincidencia 1: 1:

my_series.to_dict()
{'1': 'val_2', '2': 'val_5'}

Lo que me gustaría ver en su lugar es:

{'1': ['val_1', 'val_2'], '2': ['val_3', 'val_4', 'val_5']}

Puedo lograr esto haciendo

{idx:list(my_series[idx]) for idx in set(my_series.index)}
{'2': ['val_3', 'val_4', 'val_5'], '1': ['val_1', 'val_2']}

Lo que me gustaría saber es si hay una forma más nativa de hacer esto en los pandas, o si esta es la mejor manera de manejar el problema.

1
John Rouhana 9 may. 2019 a las 20:30

3 respuestas

La mejor respuesta

Prueba esto:

my_series.groupby(level=0).agg(list).to_dict()

Out[358]: {'1': ['val_1', 'val_2'], '2': ['val_3', 'val_4', 'val_5']}
1
Andy L. 9 may. 2019 a las 18:13

Recreando tu situación ...

>>> import pandas as pd
>>> df = pd.DataFrame([["a",10], ["b", 11], ["c", 12], ["a", 13]], 
                      columns=["letters", "numbers"])
>>> df.set_index("letters", inplace=True)
>>> print(df.to_dict())
{'numbers': {'a': 13, 'b': 11, 'c': 12}}

Ok ahora estamos en tu situación. Vamos a darle un nuevo índice temporalmente y agrupar por el índice duplicado.

>>> df.reset_index(inplace=True)
>>> groups = df.groupby(["letters"])
>>> new_df = groups.numbers.apply(list)
>>> print(new_df.to_dict())
{'a': [10, 13], 'b': [11], 'c': [12]}

Que es lo que pediste

1
samfr 9 may. 2019 a las 17:50

Pruebe lo siguiente:

my_series.reset_index().groupby('index')[0].apply(list).to_dict()

Rendimientos:

{'1': ['val_1', 'val_2'], '2': ['val_3', 'val_4', 'val_5']}
1
rahlf23 9 may. 2019 a las 17:48