Użyj oryginalnych indeksów df1, aby utworzyć serię:
df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
Edytuj 2015
Niektórzy zgłosili, że dostali SettingWithCopyWarning
ten kod.
Jednak kod nadal działa idealnie z bieżącą wersją pandy 0.16.1.
>>> sLength = len(df1['a'])
>>> df1
a b c d
6 -0.269221 -0.026476 0.997517 1.294385
8 0.917438 0.847941 0.034235 -0.448948
>>> df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
a b c d e
6 -0.269221 -0.026476 0.997517 1.294385 1.757167
8 0.917438 0.847941 0.034235 -0.448948 2.228131
>>> p.version.short_version
'0.16.1'
Te SettingWithCopyWarning
cele, aby poinformować o możliwie nieprawidłowej cesji na kopię Dataframe. Nie musi to oznaczać, że zrobiłeś to źle (może powodować fałszywe alarmy), ale od 0.13.0 informuje, że istnieją bardziej odpowiednie metody do tego samego celu. Następnie, jeśli pojawi się ostrzeżenie, postępuj zgodnie z jego radą: Spróbuj zamiast tego użyć .loc [row_index, col_indexer] = wartość
>>> df1.loc[:,'f'] = pd.Series(np.random.randn(sLength), index=df1.index)
>>> df1
a b c d e f
6 -0.269221 -0.026476 0.997517 1.294385 1.757167 -0.050927
8 0.917438 0.847941 0.034235 -0.448948 2.228131 0.006109
>>>
W rzeczywistości jest to obecnie bardziej wydajna metoda opisana w dokumentach pandas
Edytuj 2017
Jak wskazano w komentarzach i @Alexander, obecnie najlepszą metodą dodawania wartości Serii jako nowej kolumny DataFrame może być assign
:
df1 = df1.assign(e=pd.Series(np.random.randn(sLength)).values)
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead
kwargs
słownik, tak jak:df1 = df1.assign(**{'e': p.Series(np.random.randn(sLength)).values})
To prosty sposób dodania nowej kolumny:
df['e'] = e
źródło
e
(Series(np.random.randn(sLength))
) generuje indeksowane Serie 0-n. Jeśli przypiszesz to do df1, otrzymasz trochę komórek NaN.my_dataframe = pd.DataFrame(columns=('foo', 'bar'))
.Zakładam, że wartości indeksu są
e
zgodne z tymi wdf1
.Najprostszym sposobem na zainicjowanie nowej kolumny o nazwie
e
i przypisanie jej wartości z seriie
:przypisać (Pandy 0.16.0+)
Począwszy od wersji Panda 0.16.0, można również użyć
assign
, która przypisuje nowe kolumny do DataFrame i zwraca nowy obiekt (kopię) ze wszystkimi oryginalnymi kolumnami oprócz nowych.Zgodnie z tym przykładem (który zawiera również kod źródłowy
assign
funkcji), możesz również dołączyć więcej niż jedną kolumnę:W kontekście twojego przykładu:
Opis tej nowej funkcji, która została wprowadzona po raz pierwszy, można znaleźć tutaj .
źródło
df['e'] = e.values
) nie tworzy kopii ramki danych, podczas gdy druga opcja (używadf.assign
) robi? W przypadku wielu nowych kolumn dodawanych kolejno i dużych ramek danych oczekiwałbym znacznie lepszej wydajności pierwszej metody.assign
jest połączenie działań.df.assign(**df.mean().add_prefix('mean_'))
df_new = pd.concat([df1, df2], axis=1)
,ignore_index=False
domyślnie zaznaczając to .Wygląda na to, że w najnowszych wersjach Pandas można użyć df.assign :
df1 = df1.assign(e=np.random.randn(sLength))
Nie produkuje
SettingWithCopyWarning
.źródło
Wykonanie tego bezpośrednio przez NumPy będzie najbardziej wydajne:
Zwróć uwagę, że moją pierwotną (bardzo starą) sugestią było użycie
map
(która jest znacznie wolniejsza):źródło
.map
aby użyć istniejącej serii zamiastlambda
? Staramdf1['e'] = df1['a'].map(lambda x: e)
albodf1['e'] = df1['a'].map(e)
ale to nie to, czego potrzebują. (Jestem nowy w pyhon i twoja poprzednia odpowiedź już mi pomogła)e
Serię, to nie musisz jej używaćmap
, użyjdf['e']=e
(odpowiedź @joaquins).Super proste przypisanie kolumny
Ramka danych pandy jest implementowana jako uporządkowany zrzut kolumn.
Oznacza to, że
__getitem__
[]
można użyć nie tylko do uzyskania określonej kolumny, ale również__setitem__
[] =
można też przypisać nową kolumnę.Na przykład do tej ramki danych można dodać kolumnę, używając po prostu
[]
akcesoriumPamiętaj, że działa to nawet wtedy, gdy indeks ramki danych jest wyłączony.
[] = droga do zrobienia, ale uważaj!
Jeśli jednak masz
pd.Series
i spróbuj przypisać go do ramki danych, w której indeksy są wyłączone, napotkasz problemy. Zobacz przykład:Wynika to z faktu, że
pd.Series
domyślnie indeks jest wyliczany od 0 do n. A[] =
metoda pand stara się być „inteligentna”Co się właściwie dzieje?
Podczas korzystania z
[] =
metody pandy cicho wykonują zewnętrzne połączenie lub scalanie zewnętrzne przy użyciu indeksu lewej ramki danych i indeksu prawej serii.df['column'] = series
Dygresja
To szybko powoduje dysonans poznawczy, ponieważ
[]=
metoda stara się robić wiele różnych rzeczy w zależności od danych wejściowych, a wyniku nie można przewidzieć, chyba że wiesz, jak działają pandy. Dlatego odradzałbym[]=
podstawy kodu, ale podczas eksploracji danych w notatniku jest w porządku.Obejście problemu
Jeśli masz
pd.Series
i chcesz przypisać go od góry do dołu lub jeśli kodujesz kod produkcyjny i nie masz pewności co do kolejności indeksowania, warto zabezpieczyć się przed tego rodzaju problemami.Możesz obniżyć
pd.Series
do anp.ndarray
lub alist
, to załatwi sprawę.lub
Ale to nie jest bardzo jednoznaczne.
Może przyjdzie jakiś koder i powie „Hej, to wygląda na zbędne, po prostu zoptymalizuję to”.
Wyraźny sposób
Ustawienie indeksu
pd.Series
na indeks indeksudf
jest jawne.Lub bardziej realistycznie, prawdopodobnie masz
pd.Series
już dostępny.Można teraz przypisać
Alternatywny sposób z
df.reset_index()
Ponieważ dysonans indeksu jest problemem, jeśli uważasz, że indeks ramki danych nie powinien dyktować rzeczy, możesz po prostu upuścić indeks, powinno to być szybsze, ale nie jest bardzo czyste, ponieważ Twoja funkcja prawdopodobnie wykonuje teraz dwie rzeczy.
Uwaga na
df.assign
Choć
df.assign
stał się bardziej wyraźny, co robisz, to faktycznie ma te same problemy jak wyżej[]=
Uważaj tylko,
df.assign
aby twoja kolumna nie została wywołanaself
. Spowoduje to błędy. Todf.assign
śmierdzi , ponieważ w funkcji znajdują się tego rodzaju artefakty.Możesz powiedzieć: „No cóż, wtedy po prostu nie
self
użyję”. Ale kto wie, jak ta funkcja zmieni się w przyszłości, aby wspierać nowe argumenty. Być może nazwa kolumny będzie argumentem w nowej aktualizacji pand, powodując problemy z aktualizacją.źródło
[] =
metody, pandy cicho wykonują łączenie zewnętrzne lub scalanie zewnętrzne ”. To najważniejsza informacja w całym temacie. Ale czy możesz podać link do oficjalnej dokumentacji dotyczącej działania[]=
operatora?Najłatwiejsze sposoby:
W ten sposób unikasz tak zwanego indeksowania łańcuchowego, ustawiając nowe wartości w obiekcie pandy. Kliknij tutaj, aby przeczytać dalej .
źródło
Jeśli chcesz ustawić całą nową kolumnę na początkową wartość podstawową (np.
None
), Możesz to zrobić:df1['e'] = None
To faktycznie przypisałoby komórce typ „obiektu”. Później możesz swobodnie umieszczać złożone typy danych, takie jak lista, w poszczególnych komórkach.
źródło
Mam bał
SettingWithCopyWarning
i nie została ustalona za pomocą składni iloc. Mój DataFrame został utworzony przez read_sql ze źródła ODBC. Korzystając z sugestii Lowtech powyżej, następujące działania działały dla mnie:To działało dobrze, aby wstawić kolumnę na końcu. Nie wiem, czy jest to najbardziej wydajny, ale nie lubię komunikatów ostrzegawczych. Myślę, że istnieje lepsze rozwiązanie, ale nie mogę go znaleźć i myślę, że zależy to od jakiegoś aspektu indeksu.
Uwaga . To działa tylko raz i wyświetli komunikat o błędzie przy próbie zastąpienia istniejącej kolumny.
Uwaga Jak wyżej i od 0.16.0 przypisanie jest najlepszym rozwiązaniem. Zobacz dokumentację http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.assign.html#pandas.DataFrame.assign Działa dobrze dla typu przepływu danych, w którym nie zastępuje się wartości pośrednich.
źródło
list_of_e
który ma odpowiednie dane.df['e'] = list_of_e
źródło
tolist()
polecenie może być pomocne.Jeśli kolumna, którą próbujesz dodać, jest zmienną serii, po prostu:
Działa to dobrze, nawet jeśli zastępujesz istniejącą kolumnę. Po prostu wpisz nową nazwę_kolumny taką samą jak kolumna, którą chcesz zastąpić. Po prostu zastąpi istniejące dane kolumny nowymi danymi serii.
źródło
Jeśli ramka danych i obiekt serii mają ten sam indeks ,
pandas.concat
działa również tutaj:W przypadku, gdy nie mają tego samego indeksu:
źródło
Niezawodny:
Przykład:
źródło
Dodam tylko, że podobnie jak w przypadku hum3 ,
.loc
nie rozwiązałem problemuSettingWithCopyWarning
i musiałem się do niego odwołaćdf.insert()
. W moim przypadku fałszywie dodatni został wygenerowany przez „fałszywe” indeksowanie łańcuchadict['a']['e']
, gdzie'e'
jest nowa kolumna idict['a']
jest to DataFrame pochodząca ze słownika.Pamiętaj również, że jeśli wiesz, co robisz, możesz przełączyć ostrzeżenie za pomocą
pd.options.mode.chained_assignment = None
i niż użyć jednego z innych podanych tutaj rozwiązań.źródło
aby wstawić nową kolumnę w danym miejscu (0 <= loc <= ilość kolumn) w ramce danych, wystarczy użyć Dataframe.insert:
Dlatego jeśli chcesz dodać kolumnę e na końcu ramki danych o nazwie df , możesz użyć:
wartość może być Serią, liczbą całkowitą (w którym to przypadku wszystkie komórki zostaną wypełnione tą jedną wartością) lub strukturą podobną do tablicy
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.insert.html
źródło
Przed przypisaniem nowej kolumny, jeśli indeksowałeś dane, musisz posortować indeks. Przynajmniej w moim przypadku musiałem:
źródło
Należy jednak zauważyć, że jeśli to zrobisz
będzie to skutecznie lewy łącznik w pliku df1.index. Więc jeśli chcesz uzyskać efekt łączenia zewnętrznego , moim prawdopodobnie niedoskonałym rozwiązaniem jest utworzenie ramki danych z wartościami indeksu obejmującymi wszechświat twoich danych, a następnie użyć powyższego kodu. Na przykład,
źródło
Szukałem ogólnego sposobu dodawania kolumny
numpy.nan
s do ramki danych bez głupotySettingWithCopyWarning
.Z następujących czynności:
numpy
macierzy NaN w liniiWymyśliłem to:
źródło
Aby dodać nową kolumnę „e” do istniejącej ramki danych
źródło
Ze względu na kompletność - kolejne rozwiązanie wykorzystujące metodę DataFrame.eval () :
Dane:
Rozwiązanie:
źródło
Aby utworzyć pustą kolumnę
źródło
Oto co zrobiłem ... Ale jestem całkiem nowy w pandach i ogólnie w Pythonie, więc nie obiecuję.
źródło
Jeśli się
SettingWithCopyWarning
pojawi, łatwym rozwiązaniem jest skopiowanie ramki danych, do której próbujesz dodać kolumnę.źródło