2015-07-17 28 views
5

Simile a questa domanda How to add an empty column to a dataframe?, sono interessato a conoscere il modo migliore per aggiungere una colonna di elenchi vuoti a un DataFrame.Aggiungi colonna di liste vuote a DataFrame

Quello che sto cercando di fare è fondamentalmente inizializzare una colonna e mentre eseguo l'iterazione sulle righe per elaborarne alcune, quindi aggiungere un elenco completo in questa nuova colonna per sostituire il valore inizializzato.

Ad esempio, se al di sotto è mio dataframe iniziale:

df = pd.DataFrame(d = {'a': [1,2,3], 'b': [5,6,7]}) # Sample DataFrame 

>>> df 
    a b 
0 1 5 
1 2 6 
2 3 7 

Poi voglio finire infine con qualcosa di simile, in cui ogni riga è stato elaborato separatamente (risultati dei campioni mostrati):

>>> df 
    a b   c 
0 1 5  [5, 6] 
1 2 6  [9, 0] 
2 3 7 [1, 2, 3] 

Ovviamente, se provo a inizializzare come df['e'] = [] come farebbe con qualsiasi altra costante, si pensa che sto provando ad aggiungere una sequenza di elementi con lunghezza 0, e quindi fallisce.

Se provo a inizializzare una nuova colonna come None o NaN, eseguo i seguenti problemi quando si tenta di assegnare un elenco a un percorso.

df['d'] = None 

>>> df 
    a b  d 
0 1 5 None 
1 2 6 None 
2 3 7 None 

Issue 1 (sarebbe perfetto se posso ottenere questo approccio al lavoro Forse qualcosa di banale che mi manca!):

>>> df.loc[0,'d'] = [1,3] 

... 
ValueError: Must have equal len keys and value when setting with an iterable 

Numero 2 (questo funziona, ma non senza un avvertimento perché non è garantito per funzionare come previsto):

>>> df['d'][0] = [1,3] 

C:\Python27\Scripts\ipython:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame 

Perciò io ricorrere a inizializzare con liste vuote ed estendentesi secondo necessità. Ci sono un paio di metodi che posso pensare di inizializzare in questo modo, ma c'è un modo più semplice?

Metodo 1:

df['empty_lists1'] = [list() for x in range(len(df.index))] 

>>> df 
    a b empty_lists1 
0 1 5    [] 
1 2 6    [] 
2 3 7    [] 

Metodo 2:

df['empty_lists2'] = df.apply(lambda x: [], axis=1) 

>>> df 
    a b empty_lists1 empty_lists2 
0 1 5    []    [] 
1 2 6    []    [] 
2 3 7    []    [] 

Riassunto delle domande:

C'è qualche cambiamento sintassi minore che può essere affrontato nel numero 1 che può permettere un elenco da assegnare a un campo inizializzato None/NaN?

In caso contrario, qual è il modo migliore per inizializzare una nuova colonna con elenchi vuoti?

+0

nel numero 1 e 2 si inizia a fare riferimento a una colonna d. a cosa si riferisce? – AZhao

+0

e per quello che vale mi piace approccio 2. piuttosto semplice. – AZhao

+0

La colonna ''d'' è solo una colonna di valori inizializzati' None' o 'NaN', come definiti poco prima dei problemi. – vk1011

risposta

11

più Un modo è quello di utilizzare np.empty:

df['empty_list'] = np.empty((len(df), 0)).tolist() 

Si potrebbe anche staccare .index in "Metodo 1" quando si cerca di trovare len di df.

df['empty_list'] = [[] for _ in range(len(df))] 

scopre, np.empty è più veloce ...

In [1]: import pandas as pd 

In [2]: df = pd.DataFrame(pd.np.random.rand(1000000, 5)) 

In [3]: timeit df['empty1'] = pd.np.empty((len(df), 0)).tolist() 
10 loops, best of 3: 127 ms per loop 

In [4]: timeit df['empty2'] = [[] for _ in range(len(df))] 
10 loops, best of 3: 193 ms per loop 

In [5]: timeit df['empty3'] = df.apply(lambda x: [], axis=1) 
1 loops, best of 3: 5.89 s per loop 
+0

Grazie. Sì, l'approccio 'np.empty' sembra più veloce. Anche il 'len (df.index)' è in effetti più veloce di 'len (df)'. – vk1011

2

Ho cronometrato tutti i tre metodi nella risposta accettata, il più veloce ha impiegato 216 ms sulla mia macchina. Tuttavia, questo ha preso solo 28 ms:

df['empty4'] = [[]] * len(df)

Nota: Allo stesso modo, df['e5'] = [set()] * len(df) presero anche 28ms.

+0

Ho cercato di capire questo per 2 ore, questa soluzione è il vero affare. – JoelBondurant

Problemi correlati