2015-07-17 16 views
5

Podobne do tego pytania How to add an empty column to a dataframe?, Jestem zainteresowany poznaniem najlepszego sposobu dodania kolumny pustych list do DataFrame.Dodaj kolumnę pustych list do DataFrame

Co próbuję zrobić, to w zasadzie zainicjować kolumnę i jako I iteracyjne nad wierszami, aby przetworzyć niektóre z nich, a następnie dodać wypełnioną listę w tej nowej kolumnie, aby zastąpić zainicjowaną wartość.

Na przykład, jeżeli poniżej jest mój początkowy DataFrame:

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 

Następnie chcę ostatecznie skończyć z czymś takim, gdzie każdy wiersz został przetworzony oddzielnie (wyniki próbek pokazano):

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

Oczywiście, jeśli spróbuję zainicjować jak df['e'] = [], tak jak w przypadku każdej innej stałej, to myślę, że próbuję dodać sekwencję elementów o długości 0, a więc nie.

Jeśli spróbuję zainicjować nową kolumnę jako None lub NaN, podczas próby przypisania listy do lokalizacji napotkam następujące problemy.

df['d'] = None 

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

Issue 1 (to byłoby idealne, jeśli mogę to podejście do pracy Może coś trywialne mi brakuje!):

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

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

Issue 2 (ten działa, ale nie bez ostrzeżenia ponieważ nie ma gwarancji, że działa zgodnie z przeznaczeniem):

>>> 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 

W związku z tym uciekam się do inicjowania z pustymi listami i rozszerzania ich w razie potrzeby. Jest kilka metod, które mogę zainicjować w ten sposób, ale czy istnieje bardziej prosty sposób?

Metoda 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    [] 

Metoda 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    []    [] 

Zestawienie pytań:

Czy istnieje niewielkie zmiany składni, które mogą być skierowane w Issue 1, które może pozwolić listę do przypisania do zainicjowanego pola None/NaN?

Jeśli nie, to jaki jest najlepszy sposób na zainicjowanie nowej kolumny z pustymi listami?

+0

w numerze 1 i 2 zaczynasz odsyłać do kolumny d. o czym to się mówi? – AZhao

+0

i za to, co warto, lubię podejście 2. całkiem proste imo. – AZhao

+0

Kolumna '' d'' jest po prostu kolumną wartości inicjalizowanych 'None' lub' NaN', zdefiniowaną tuż przed problemami. – vk1011

Odpowiedz

11

Jeszcze sposobem jest użycie np.empty:

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

Można również strącać .index w swoim "Metoda 1", gdy próbuje znaleźć len z df.

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

Okazuje się, np.empty jest szybsza ...

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

Dzięki. Tak, podejście 'np.empty' wygląda szybciej. "Len (df.index)" również faktycznie jest podobnie szybszy niż "len (df)". – vk1011

2

Wyliczyłem wszystkie trzy metody w zaakceptowanej odpowiedzi, najszybszy wziął 216 ms na moim komputerze. Jednak to było tylko 28 MS:

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

Uwaga: Podobnie df['e5'] = [set()] * len(df) wziął również 28ms.

+0

Próbowałem to zrozumieć przez 2 godziny, to rozwiązanie jest prawdziwą okazją. – JoelBondurant

Powiązane problemy