Dodaj kolumnę w ramce danych z listy

98

Mam ramkę danych z kilkoma kolumnami takimi jak ta:

A   B   C  
0   
4
5
6
7
7
6
5

Dopuszczalny zakres wartości w tylko od 0 do 7 .

Mam też listę 8 elementów, takich jak ta:

List=[2,5,6,8,12,16,26,32]  //There are only 8 elements in this list

Jeśli element w kolumnie A to n , muszę wstawić n- ty element z listy do nowej kolumny, powiedz „D”.

Jak mogę to zrobić za jednym razem bez zapętlania się po całej ramce danych?

Wynikowa ramka danych wyglądałaby następująco:

A   B   C   D
0           2
4           12
5           16
6           26
7           32
7           32
6           26
5           16

Uwaga: ramka danych jest ogromna, a iteracja jest ostatnią opcją. Ale w razie potrzeby mogę również ułożyć elementy w „Liście” w dowolnej innej strukturze danych, takiej jak dict.

grzywa
źródło
1
Myślę, że potrzebujesz (mniejszego) przykładu zabawki, z pożądanym rezultatem. Brzmi trochę niejasno.
Andy Hayden
11
Nigdy, przenigdy nie nazywaj zmiennej „List”. W dowolnym języku.
lucid_dreamer

Odpowiedzi:

51

IIUC, jeśli zmienisz swój (niestety nazwany) Listna an ndarray, możesz po prostu naturalnie go indeksować.

>>> import numpy as np
>>> m = np.arange(16)*10
>>> m[df.A]
array([  0,  40,  50,  60, 150, 150, 140, 130])
>>> df["D"] = m[df.A]
>>> df
    A   B   C    D
0   0 NaN NaN    0
1   4 NaN NaN   40
2   5 NaN NaN   50
3   6 NaN NaN   60
4  15 NaN NaN  150
5  15 NaN NaN  150
6  14 NaN NaN  140
7  13 NaN NaN  130

Tutaj zbudowałem nowy m, ale jeśli użyjesz m = np.asarray(List), to samo powinno działać: wartości w df.Adobiorą odpowiednie elementy m.


Zauważ, że jeśli używasz starej wersji numpy, być może będziesz musiał użyć m[df.A.values]zamiast tego - w przeszłości numpynie grało dobrze z innymi, a niektóre refaktoryzacje pandaspowodowały bóle głowy. Teraz sytuacja się poprawiła.

DSM
źródło
Cześć @DSM. Rozumiem, co mówisz, ale otrzymuję ten błąd: Traceback (most recent call last): File "./b.py", line 24, in <module> d["D"] = m[d.A] IndexError: unsupported iterator index
grzywa
1
@mane: urf, to stary numpybłąd. Działa d["D"] = m[d.A.values]dla Ciebie?
DSM
284

Po prostu przypisz listę bezpośrednio:

df['new_col'] = mylist

Alternatywa
Przekonwertuj listę na serię lub tablicę, a następnie przypisz:

se = pd.Series(mylist)
df['new_col'] = se.values

lub

df['new_col'] = np.array(mylist)
wróbel
źródło
3
pykernel_launcher.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy """Entry point for launching an IPython kernel.
Ilya Rusin
@sparrow użyje pd.Seriesefektu dtype ? Mam na myśli, czy pozostawi pływaki jako pływaki, a struny jako struny? A może elementy na liście będą domyślnie łańcuchami?
3kstc
2
@IlyaRusin, jest to fałszywy alarm, który w tym przypadku można zignorować. Więcej informacji: stackoverflow.com/questions/20625582/…
sparrow
1
Można to uprościć do: df ['new_col'] = pd.Series (mylist) .values
smartse
17

Rozwiązanie ulepszone w stosunku do świetnego od @sparrow.

Niech df będzie twoim zbiorem danych, i wymień listę z wartościami, które chcesz dodać do ramki danych.

Załóżmy, że chcesz nazwać swoją nową kolumnę po prostu nową_kolumną

Najpierw ułóż listę w serię:

column_values = pd.Series(mylist)

Następnie użyj funkcji wstawiania, aby dodać kolumnę. Ta funkcja ma tę zaletę, że pozwala wybrać pozycję, w której chcesz umieścić kolumnę. W poniższym przykładzie umieścimy nową kolumnę na pierwszej pozycji od lewej (ustawiając loc = 0)

df.insert(loc=0, column='new_column', value=column_values)
Salvatore Cosentino
źródło
To nie zadziała, jeśli zmienisz indeksy df na coś innego niż 1,2,3 ... w takim przypadku musisz dodać między wierszami: column_values.index = df.index
Guy s
8

Najpierw utwórzmy ramkę danych, którą miałeś, zignoruję kolumny B i C, ponieważ nie są one istotne.

df = pd.DataFrame({'A': [0, 4, 5, 6, 7, 7, 6,5]})

I mapowanie, które chcesz:

mapping = dict(enumerate([2,5,6,8,12,16,26,32]))

df['D'] = df['A'].map(mapping)

Gotowe!

print df

Wynik:

   A   D
0  0   2
1  4  12
2  5  16
3  6  26
4  7  32
5  7  32
6  6  26
7  5  16
Phil Cooper
źródło
1
Myślę, że OP już wie, jak to zrobić. Czytając, że problem polega na konstruowaniu Dz elementów Ai List(„Jeśli element w kolumnie A to n, muszę wstawić n-ty element z listy do nowej kolumny, powiedzieć„ D ”.”)
DSM
SO zmieniło się w coś w rodzaju F (* i stan niani. Dzięki @DSM za komentarz, ale nie mogłem poprawić postu, dopóki nie został sprawdzony przez innych użytkowników. A potem został odrzucony, ponieważ był za szybki. I wtedy byłem w stanie ocenić moją własną edycję. a potem jest już za późno, ponieważ gorsza (IMHO) odpowiedź została „zaakceptowana”. Tak naprawdę jest kilka meta-niani, którzy są mniej niż pomocni !!!!
Phil Cooper
Cóż, nie mogę mówić w imieniu niań, ale przekonasz się, że twoje podejście jest o rząd wielkości wolniejsze w przypadku długich tablic. Oczywiście pod innymi względami wybór między np.array(List)[df.A]i df["A"].map(dict(enumerate(List)))jest głównie kwestią preferencji.
DSM
Cześć Phil, widziałem tylko twoje rozwiązanie i komentarz DSM, ale nigdy do niego nie wróciłem, ponieważ rozwiązanie DSM działało dobrze dla mnie. Ale teraz, patrząc na twoje rozwiązanie, też działa. Uruchomiłem rozwiązanie DSM na moim zbiorze danych zawierającym około 200 tys. Wpisów i działa ono w ciągu kilku sekund ze wszystkimi innymi obliczeniami, które posiadam. Jestem zupełnie nowy w Python-pandach i osobiście nie szukałem niczego eleganckiego ani wspaniałego; cokolwiek działało, było w porządku. Ale szczerze dziękuję za rozwiązanie.
grzywa
2

Stare pytanie; ale zawsze staram się używać najszybszego kodu!

Miałem ogromną listę z 69 milionami plików uint64. np.array () był dla mnie najszybszy.

df['hashes'] = hashes
Time spent: 17.034842014312744

df['hashes'] = pd.Series(hashes).values
Time spent: 17.141014337539673

df['key'] = np.array(hashes)
Time spent: 10.724546194076538
Mehdi
źródło