Python Pandas: Cómo dividir un diccionario ordenado en una columna de un dataframe

Tengo un dataFrame como este:

id asn orgs 0 3320 {'Deutsche Telekom AG': 2288} 1 47886 {'Joyent': 16, 'Equinix (Netherlands) BV': 7} 2 47601 {'fusion services': 1024, 'GCE Global Maritime':16859} 3 33438 {'Highwinds Network Group': 893} 

Me gustaría ordenar la columna ‘orgs’ que es en realidad un diccionario y luego extraer el par (k, v) con los valores más altos en dos columnas diferentes. Me gusta esto:

 id asn org value 0 3320 'Deutsche Telekom AG' 2288 1 47886 'Joyent' 16 2 47601 'GCE Global Maritime' 16859 3 33438 'Highwinds Network Group' 893 

Actualmente estoy ejecutando este código pero no se ordena correctamente, y luego no estoy seguro de cómo extraer el par con el valor más alto.

 df.orgs.apply(lambda x : sorted(x.items(),key=operator.itemgetter(1),reverse=True)) 

que me dio una lista como esta:

 id asn orgs 0 3320 [('Deutsche Telekom AG', 2288)] 1 47886 [('Joyent', 16),( 'Equinix (Netherlands) BV', 7)] 2 47601 [('GCE Global Maritime',16859),('fusion services', 1024)] 3 33438 [('Highwinds Network Group', 893)] 

Ahora, ¿cómo puedo poner la clave y el valor más alto en dos columnas separadas? ¿Alguien puede ayudar?

Otro enfoque define una función que solo llama min en el dict y devuelve una serie para que pueda asignar a múltiples columnas (cuerpo de la función tomado de la respuesta de @Alex Martelli ):

 In [17]: def func(x): k = min(x, key=x.get) return pd.Series([k, x[k]]) df[['orgs', 'value']] = df['orgs'].apply(func) df Out[17]: asn id orgs value 0 3320 0 Deutsche Telekom AG 2288 1 47886 1 Equinix (Netherlands) BV 7 2 47601 2 fusion services 1024 3 33438 3 Highwinds Network Group 893 

EDITAR

Si sus datos tienen datos vacíos, puede probar el len :

 In [34]: df = pd.DataFrame({'id':[0,1,2,3,4], 'asn':[3320,47886,47601,33438,56], 'orgs':[{'Deutsche Telekom AG': 2288}, {'Joyent': 16, 'Equinix (Netherlands) BV': 7}, {'fusion services': 1024, 'GCE Global Maritime':16859}, {'Highwinds Network Group': 893},{}]}) df Out[34]: asn id orgs 0 3320 0 {'Deutsche Telekom AG': 2288} 1 47886 1 {'Equinix (Netherlands) BV': 7, 'Joyent': 16} 2 47601 2 {'GCE Global Maritime': 16859, 'fusion service... 3 33438 3 {'Highwinds Network Group': 893} 4 56 4 {} In [36]: def func(x): if len(x) > 0: k = min(x, key=x.get) return pd.Series([k, x[k]]) return pd.Series([np.NaN, np.NaN]) df[['orgs', 'value']] = df['orgs'].apply(func) df Out[36]: asn id orgs value 0 3320 0 Deutsche Telekom AG 2288 1 47886 1 Equinix (Netherlands) BV 7 2 47601 2 fusion services 1024 3 33438 3 Highwinds Network Group 893 4 56 4 NaN NaN 

Esto debería funcionar:

 In [1]: import pandas as pd In [2]: import operator In [3]: df = pd.DataFrame({ 'id' : [0,1,2,3], ...: 'asn' : [3320, 47886, 47601, 33438], ...: 'orgs' : [{'Deutsche Telekom AG': 2288}, {'Joyent': 16, 'Equinix (Netherlands) BV': 7}, {'fusion services': 1024, 'GCE Global Maritime':16859}, {'Highwinds Network Group': 893}] ...: }) In [4]: df.orgs, df['value'] = zip(*df.orgs.apply(lambda x : sorted(x.items(),key=operator.itemgetter(1),reverse=True)[0])) In [5]: df Out[5]: asn id orgs value 0 3320 0 Deutsche Telekom AG 2288 1 47886 1 Joyent 16 2 47601 2 GCE Global Maritime 16859 3 33438 3 Highwinds Network Group 893 

Utilicé zip(* ) y los df.orgs a df.orgs y df.value .

Para diccionarios vacíos:

 In [3]: df = pd.DataFrame({ 'id' : [0,1,2,3], ...: 'asn' : [3320, 47886, 47601, 33438], ...: 'orgs' : [{'Deutsche Telekom AG': 2288}, {'Joyent': 16, 'Equinix (Netherlands) BV': 7}, {'fusion services': 1024, 'GCE Global Maritime':16859}, {}] ...: }) In [4]: df.orgs.apply(lambda x : sorted(x.items(),key=operator.itemgetter(1),reverse=True)[0] if len(x) else ('','')) Out[4]: 0 (Deutsche Telekom AG, 2288) 1 (Joyent, 16) 2 (GCE Global Maritime, 16859) 3 (, ) Name: orgs, dtype: object In [5]: df.orgs, df['value'] = zip(*df.orgs.apply(lambda x : sorted(x.items(),key=operator.itemgetter(1),reverse=True)[0] if len(x) else ('',''))) In [6]: df Out[6]: asn id orgs value 0 3320 0 Deutsche Telekom AG 2288 1 47886 1 Joyent 16 2 47601 2 GCE Global Maritime 16859 3 33438 3