2015-01-30 23 views
14

Ho il seguente codice:come convertire un elenco in un dataframe panda

rows =[] 
for dt in new_info: 
    x = dt['state'] 
    est = dt['estimates'] 

    col_R = [val['choice'] for val in est if val['party'] == 'Rep'] 
    col_D = [val['choice'] for val in est if val['party'] == 'Dem'] 

    incumb = [val['party'] for val in est if val['incumbent'] == True ] 

    rows.append((x, col_R, col_D, incumb)) 

Ora voglio convertire la mia lista righe in un frame di dati panda. La struttura della mia lista di file è mostrata sotto e la mia lista ha 32 voci.

enter image description here

Quando converto questo in un frame di dati panda, ottengo le voci nella cornice di dati come una lista. :

pd.DataFrame(rows, columns=["State", "R", "D", "incumbent"]) 

enter image description here

Ma io voglio il mio telaio di dati come questo

enter image description here

La nuova variabile informazioni assomiglia a questo enter image description here

risposta

9

Dal momento che si mente gli oggetti nella le colonne sono liste, vorrei usare un generatore per rimuovere gli elenchi wrappi ng tuoi elementi:

import pandas as pd 
import numpy as np 
rows = [(u'KY', [u'McConnell'], [u'Grimes'], [u'Rep']), 
     (u'AR', [u'Cotton'], [u'Pryor'], [u'Dem']), 
     (u'MI', [u'Land'], [u'Peters'], [])] 

def get(r, nth): 
    '''helper function to retrieve item from nth list in row r''' 
    return r[nth][0] if r[nth] else np.nan 

def remove_list_items(list_of_records): 
    for r in list_of_records: 
     yield r[0], get(r, 1), get(r, 2), get(r, 3) 

Il generatore funziona in modo simile a questa funzione, ma invece di materializzare un elenco inutilmente in memoria, come fase intermedia, si passa solo ogni riga che sarebbe nella lista al consumatore dell'elenco di righe:

def remove_list_items(list_of_records): 
    result = [] 
    for r in list_of_records: 
     result.append((r[0], get(r, 1), get(r, 2), get(r, 3))) 
    return result 

e poi comporre il dataframe passando i dati attraverso il generatore, (o la versione lista, se lo si desidera.)

>>> df = pd.DataFrame.from_records(
     remove_list_items(rows), 
     columns=["State", "R", "D", "incumbent"]) 
>>> df 
    State   R  D incumbent 
0 KY McConnell Grimes  Rep 
1 AR  Cotton Pryor  Dem 
2 MI  Land Peters  NaN 

oppure si potrebbe usare un elenco di comprensione o un generatore di espressione (illustrato) di fare essenzialmente la stessa:

>>> df = pd.DataFrame.from_records(
     ((r[0], get(r, 1), get(r, 2), get(r, 3)) for r in rows), 
     columns=["State", "R", "D", "incumbent"]) 
+0

Vediamo [continua questa discussione in videochat] (http://chat.stackoverflow.com/stanze/69869/discussione-tra-aaron-hall-e-Elizabeth-susan-Joseph). –

7

è possibile utilizzare alcune costruito in manipolazione lista pitone e fare qualcosa di simile:

df['col1'] = df['col1'].apply(lambda i: ''.join(i)) 

che produrrà:

col1 col2 
0 a [d] 
1 b [e] 
2 c [f] 

Ovviamente col2 non è stato formattato per mostrare il contrasto.

Modifica

Come richiesto dal OP, se si desidera implementare un apply(lambda...) a tutte le colonne, allora è possibile impostare in modo esplicito ogni colonna con una linea che assomiglia a quello di cui sopra sostituendo 'col1' con ciascuno dei nomi di colonna si desidera modificare o si può semplicemente ciclo sulle colonne di questo tipo:

se si dispone di un frame di dati di tipo

x = [['a'],['b'],['c'],['d']] 
y = [['e'],['f'],['g'],['h']] 
z = [['i'],['j'],['k'],['l']] 

df = pd.DataFrame({'col1':x, 'col2':y, 'col3':z}) 

allora si può ciclo sulle colonne

for col in df.columns: 
    df[col] = df[col].apply(lambda i: ''.join(i)) 

che converte un frame di dati che inizia come:

col1 col2 col3 
0 [a] [e] [i] 
1 [b] [f] [j] 
2 [c] [g] [k] 
3 [d] [h] [l] 

e diventa

col1 col2 col3 
0 a e i 
1 b f j 
2 c g k 
3 d h l 
+0

@ElizabethSusanJoseph la mia soluzione non risolve il problema? –

+0

ma come posso applicare questo a tutto il mio data frame ?? puoi modificare la tua risposta alla mia domanda, sarebbe davvero utile –

+0

new_df = pd.DataFrame (righe, colonne = ["Stato", "R", "D", "incumbent"]) new_df [['R' , 'D', 'incumbent']]. Applica (lambda i: '' .join (i)), sto ricevendo un errore se eseguo il tuo codice –

Problemi correlati