Saya memiliki berikut diindeks DataFrame dengan nama kolom dan baris tidak - nomor terus menerus:
a b c d
2 0.671399 0.101208 -0.181532 0.241273
3 0.446172 -0.243316 0.051767 1.577318
5 0.614758 0.075793 -0.451460 -0.012493
Saya ingin menambahkan kolom baru, 'e'
, untuk data-data yang ada bingkai dan tidak ingin mengubah apa pun dalam data frame (yaitu, kolom baru selalu memiliki panjang yang sama sebagai DataFrame).
0 -0.335485
1 -1.166658
2 -0.385571
dtype: float64
Saya mencoba versi yang berbeda dari bergabung
, menambah
, menggabungkan
, tapi saya tidak mendapatkan hasil yang saya inginkan, hanya kesalahan paling. Bagaimana saya dapat menambahkan kolom e
untuk contoh di atas?
Gunakan asli df1 indeks untuk membuat seri:
df1['e'] = pd.Series(np.random.randn(sLength), index=df1.index)
Edit 2015
Beberapa dilaporkan mendapatkan SettingWithCopyWarning
dengan kode ini.
Namun, kode yang masih berjalan sempurna dengan saat ini panda versi 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'
The SettingWithCopyWarning
bertujuan untuk menginformasikan mungkin tidak valid penugasan pada salinan Dataframe. Itu doesn't selalu mengatakan anda melakukan hal yang salah (hal ini dapat memicu positif palsu) tapi dari 0.13.0 membiarkan anda tahu ada banyak metode yang memadai untuk tujuan yang sama. Kemudian, jika anda mendapatkan peringatan, hanya mengikuti saran: Mencoba menggunakan .loc[row_index,col_indexer] = nilai bukan
>>> 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
>>>
Pada kenyataannya, ini adalah saat ini metode yang lebih efisien sebagai dijelaskan di panda docs
Edit 2017
Seperti yang ditunjukkan di komentar dan oleh @Alexander, saat ini metode terbaik untuk menambahkan nilai-nilai dari sebuah Seri baru kolom DataFrame bisa menggunakan menetapkan
:
df1 = df1.assign(e=pd.Series(np.random.randn(sLength)).values)
saya ingin menambahkan kolom baru, 'e', untuk data-data yang ada bingkai dan tidak mengubah apa pun dalam data frame. (Seri selalu punya panjang yang sama sebagai dataframe.)
Saya berasumsi bahwa nilai indeks di e
pertandingan mereka di df1
.
Cara termudah untuk memulai sebuah kolom baru bernama e
, dan menetapkan nilai-nilai dari seri e
:
df['e'] = e.values
menetapkan (Panda 0.16.0+)
Sebagai Panda 0.16.0, anda juga dapat menggunakan menetapkan
, yang memberikan kolom baru ke DataFrame dan mengembalikan sebuah objek baru (copy) dengan semua kolom asli selain yang baru.
df1 = df1.assign(e=e.values)
Sebagai per contoh (yang juga mencakup kode sumber menetapkan
fungsi), anda juga dapat menyertakan lebih dari satu kolom:
df = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
>>> df.assign(mean_a=df.a.mean(), mean_b=df.b.mean())
a b mean_a mean_b
0 1 3 1.5 3.5
1 2 4 1.5 3.5
Dalam konteks dengan contoh:
np.random.seed(0)
df1 = pd.DataFrame(np.random.randn(10, 4), columns=['a', 'b', 'c', 'd'])
mask = df1.applymap(lambda x: x <-0.7)
df1 = df1[-mask.any(axis=1)]
sLength = len(df1['a'])
e = pd.Series(np.random.randn(sLength))
>>> df1
a b c d
0 1.764052 0.400157 0.978738 2.240893
2 -0.103219 0.410599 0.144044 1.454274
3 0.761038 0.121675 0.443863 0.333674
7 1.532779 1.469359 0.154947 0.378163
9 1.230291 1.202380 -0.387327 -0.302303
>>> e
0 -1.048553
1 -1.420018
2 -1.706270
3 1.950775
4 -0.509652
dtype: float64
df1 = df1.assign(e=e.values)
>>> df1
a b c d e
0 1.764052 0.400157 0.978738 2.240893 -1.048553
2 -0.103219 0.410599 0.144044 1.454274 -1.420018
3 0.761038 0.121675 0.443863 0.333674 -1.706270
7 1.532779 1.469359 0.154947 0.378163 1.950775
9 1.230291 1.202380 -0.387327 -0.302303 -0.509652
Deskripsi dari fitur baru ini ketika pertama kali diperkenalkan dapat ditemukan di sini.
Tampaknya dalam beberapa Panda versi yang cara untuk pergi adalah dengan menggunakan df.assign:
df1 = df1.menetapkan(e=np.acak.randn(sLength))
Itu doesn't menghasilkan SettingWithCopyWarning
.
Lakukan hal ini secara langsung via NumPy akan menjadi yang paling efisien:
df1['e'] = np.random.randn(sLength)
Catatan asli saya (sangat tua) saran untuk menggunakan peta
(yang lebih lambat):
df1['e'] = df1['a'].map(lambda x: np.random.random())
Sebuah panda dataframe diimplementasikan sebagai aplikasi yang memerintahkan dict kolom.
Ini berarti bahwa __getitem__
[]
tidak hanya dapat digunakan untuk mendapatkan suatu kolom tertentu, tetapi __setitem__
[] =
dapat digunakan untuk menetapkan kolom baru.
Misalnya, ini dataframe dapat memiliki kolom yang ditambahkan ke dalamnya dengan hanya menggunakan []
accessor
size name color
0 big rose red
1 small violet blue
2 small tulip red
3 small harebell blue
df['protected'] = ['no', 'no', 'no', 'yes']
size name color protected
0 big rose red no
1 small violet blue no
2 small tulip red no
3 small harebell blue yes
Catatan bahwa ini bekerja bahkan jika indeks dataframe adalah off.
df.index = [3,2,1,0]
df['protected'] = ['no', 'no', 'no', 'yes']
size name color protected
3 big rose red no
2 small violet blue no
1 small tulip red no
0 small harebell blue yes
Namun, jika anda memiliki pd.Seri
dan mencoba untuk menetapkan ke dataframe di mana indeks off, anda akan berjalan ke dalam kesulitan. Lihat contoh:
df['protected'] = pd.Series(['no', 'no', 'no', 'yes'])
size name color protected
3 big rose red yes
2 small violet blue no
1 small tulip red no
0 small harebell blue no
Hal ini karena pd.Seri
secara default memiliki indeks dihitung dari 0 sampai n. Dan panda [] =
dengan metode mencoba untuk menjadi "smart"
Ketika anda menggunakan [] =
metode panda diam-diam melakukan outer join atau luar merge menggunakan telunjuk tangan kiri dataframe dan telunjuk tangan kanan seri. df['kolom'] = seri
Ini dengan cepat menyebabkan disonansi kognitif, sejak []=
metode ini mencoba untuk melakukan banyak hal yang berbeda tergantung pada input, dan hasilnya tidak dapat diprediksi kecuali anda baru tahu bagaimana panda bekerja. Oleh karena itu saya akan saran terhadap []=
dalam kode basa, tetapi ketika anda menjelajahi data di notebook, itu baik-baik saja.
Jika anda memiliki pd.Seri
dan ingin ditetapkan dari atas ke bawah, atau jika anda adalah coding produktif kode dan anda tidak yakin indeks pesanan, itu adalah layak untuk menjaga untuk masalah semacam ini.
Anda bisa tertunduk pd.Seri
ke np.ndarray
atau daftar
, ini akan melakukan trik.
df['protected'] = pd.Series(['no', 'no', 'no', 'yes']).values
atau
df['protected'] = list(pd.Series(['no', 'no', 'no', 'yes']))
Tapi ini tidak terlalu eksplisit.
Beberapa coder mungkin datang dan mengatakan "Hey, ini terlihat berlebihan, aku'll hanya mengoptimalkan ini jauh".
Pengaturan indeks pd.Seri
untuk menjadi indeks dari df
lebih eksplisit.
df['protected'] = pd.Series(['no', 'no', 'no', 'yes'], index=df.index)
Atau lebih realistis, anda mungkin memiliki pd.Seri
sudah tersedia.
protected_series = pd.Series(['no', 'no', 'no', 'yes'])
protected_series.index = df.index
3 no
2 no
1 no
0 yes
Sekarang dapat ditugaskan
df['protected'] = protected_series
size name color protected
3 big rose red no
2 small violet blue no
1 small tulip red no
0 small harebell blue yes
df.reset_index()
Sejak indeks disonansi adalah masalah, jika anda merasa bahwa indeks dataframe harus tidak menentukan hal-hal, anda hanya bisa drop index, ini harus cepat, tapi itu tidak sangat bersih, karena fungsi anda sekarang mungkin melakukan dua hal.
df.reset_index(drop=True)
protected_series.reset_index(drop=True)
df['protected'] = protected_series
size name color protected
0 big rose red no
1 small violet blue no
2 small tulip red no
3 small harebell blue yes
df.menetapkan
Sementara df.menetapkan
membuatnya lebih eksplisit apa yang anda lakukan, itu benar-benar memiliki semua masalah yang sama seperti di atas []=
df.assign(protected=pd.Series(['no', 'no', 'no', 'yes']))
size name color protected
3 big rose red yes
2 small violet blue no
1 small tulip red no
0 small harebell blue no
Hanya hati-hati dengan df.menetapkan
bahwa kolom tidak disebut diri
. Hal itu akan menyebabkan kesalahan. Hal ini membuat df.menetapkan
bau, karena ada jenis-jenis artefak dalam fungsi.
df.assign(self=pd.Series(['no', 'no', 'no', 'yes'])
TypeError: assign() got multiple values for keyword argument 'self'
Anda mungkin berkata, "aku'll hanya tidak menggunakan diri
maka". Tapi siapa yang tahu bagaimana hal ini fungsi perubahan di masa depan untuk mendukung argumen baru. Mungkin anda nama kolom akan menjadi argumen dalam update baru dari panda, menyebabkan masalah dengan upgrade.
Jika anda ingin mengatur seluruh kolom baru untuk awal nilai dasar (misalnya, None
), anda dapat melakukan ini: df1['e'] = None
Ini benar-benar akan menetapkan "objek" jenis sel. Jadi nanti anda're bebas untuk menempatkan kompleks jenis data, seperti daftar, ke sel-sel individual.
Aku punya ditakuti SettingWithCopyWarning
, dan itu bukan't tetap dengan menggunakan iloc sintaks. Saya DataFrame diciptakan oleh read_sql dari ODBC sumber. Menggunakan saran oleh lowtech di atas, berikut ini bekerja untuk saya:
df.insert(len(df.columns), 'e', pd.Series(np.random.randn(sLength), index=df.index))
Ini bekerja dengan baik untuk menyisipkan kolom di akhir. Saya don't tahu apakah itu adalah yang paling efisien, tapi aku don't seperti pesan peringatan. Saya pikir ada solusi yang lebih baik, tapi aku bisa't menemukan itu, dan saya pikir itu tergantung pada beberapa aspek dari indeks. Catatan. Bahwa ini hanya bekerja sekali dan akan memberikan pesan kesalahan jika mencoba untuk menimpa dan ada kolom. Catatan Seperti di atas dan dari 0.16.0 menetapkan adalah solusi terbaik. Lihat dokumentasi http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.assign.html#pandas.DataFrame.assign Bekerja dengan baik untuk data jenis aliran mana anda don't menimpa nilai-nilai menengah.
list_of_e
yang memiliki data yang relevan. df['e'] = list_of_e
Jika kolom anda mencoba untuk menambahkan adalah serangkaian variabel kemudian hanya :
df["new_columns_name"]=series_variable_name #this will do it for you
Ini bekerja dengan baik bahkan jika anda mengganti yang sudah ada kolom.cukup ketik new_columns_name sama seperti kolom yang ingin anda ganti.Itu hanya akan menimpa kolom yang ada dengan data baru seri data.
Sangat mudah:
df.loc[:, 'NewCol'] = 'New_Val'
Contoh:
df = pd.DataFrame(data=np.random.randn(20, 4), columns=['A', 'B', 'C', 'D'])
df
A B C D
0 -0.761269 0.477348 1.170614 0.752714
1 1.217250 -0.930860 -0.769324 -0.408642
2 -0.619679 -1.227659 -0.259135 1.700294
3 -0.147354 0.778707 0.479145 2.284143
4 -0.529529 0.000571 0.913779 1.395894
5 2.592400 0.637253 1.441096 -0.631468
6 0.757178 0.240012 -0.553820 1.177202
7 -0.986128 -1.313843 0.788589 -0.707836
8 0.606985 -2.232903 -1.358107 -2.855494
9 -0.692013 0.671866 1.179466 -1.180351
10 -1.093707 -0.530600 0.182926 -1.296494
11 -0.143273 -0.503199 -1.328728 0.610552
12 -0.923110 -1.365890 -1.366202 -1.185999
13 -2.026832 0.273593 -0.440426 -0.627423
14 -0.054503 -0.788866 -0.228088 -0.404783
15 0.955298 -1.430019 1.434071 -0.088215
16 -0.227946 0.047462 0.373573 -0.111675
17 1.627912 0.043611 1.743403 -0.012714
18 0.693458 0.144327 0.329500 -0.655045
19 0.104425 0.037412 0.450598 -0.923387
df.drop([3, 5, 8, 10, 18], inplace=True)
df
A B C D
0 -0.761269 0.477348 1.170614 0.752714
1 1.217250 -0.930860 -0.769324 -0.408642
2 -0.619679 -1.227659 -0.259135 1.700294
4 -0.529529 0.000571 0.913779 1.395894
6 0.757178 0.240012 -0.553820 1.177202
7 -0.986128 -1.313843 0.788589 -0.707836
9 -0.692013 0.671866 1.179466 -1.180351
11 -0.143273 -0.503199 -1.328728 0.610552
12 -0.923110 -1.365890 -1.366202 -1.185999
13 -2.026832 0.273593 -0.440426 -0.627423
14 -0.054503 -0.788866 -0.228088 -0.404783
15 0.955298 -1.430019 1.434071 -0.088215
16 -0.227946 0.047462 0.373573 -0.111675
17 1.627912 0.043611 1.743403 -0.012714
19 0.104425 0.037412 0.450598 -0.923387
df.loc[:, 'NewCol'] = 0
df
A B C D NewCol
0 -0.761269 0.477348 1.170614 0.752714 0
1 1.217250 -0.930860 -0.769324 -0.408642 0
2 -0.619679 -1.227659 -0.259135 1.700294 0
4 -0.529529 0.000571 0.913779 1.395894 0
6 0.757178 0.240012 -0.553820 1.177202 0
7 -0.986128 -1.313843 0.788589 -0.707836 0
9 -0.692013 0.671866 1.179466 -1.180351 0
11 -0.143273 -0.503199 -1.328728 0.610552 0
12 -0.923110 -1.365890 -1.366202 -1.185999 0
13 -2.026832 0.273593 -0.440426 -0.627423 0
14 -0.054503 -0.788866 -0.228088 -0.404783 0
15 0.955298 -1.430019 1.434071 -0.088215 0
16 -0.227946 0.047462 0.373573 -0.111675 0
17 1.627912 0.043611 1.743403 -0.012714 0
19 0.104425 0.037412 0.450598 -0.923387 0
Jika data frame dan Serangkaian objek yang memiliki indeks yang sama, panda.concat
juga karya-karya berikut ini:
import pandas as pd
df
# a b c d
#0 0.671399 0.101208 -0.181532 0.241273
#1 0.446172 -0.243316 0.051767 1.577318
#2 0.614758 0.075793 -0.451460 -0.012493
e = pd.Series([-0.335485, -1.166658, -0.385571])
e
#0 -0.335485
#1 -1.166658
#2 -0.385571
#dtype: float64
# here we need to give the series object a name which converts to the new column name
# in the result
df = pd.concat([df, e.rename("e")], axis=1)
df
# a b c d e
#0 0.671399 0.101208 -0.181532 0.241273 -0.335485
#1 0.446172 -0.243316 0.051767 1.577318 -1.166658
#2 0.614758 0.075793 -0.451460 -0.012493 -0.385571
Dalam kasus mereka don't memiliki indeks yang sama:
e.index = df.index
df = pd.concat([df, e.rename("e")], axis=1)
Satu hal yang perlu dicatat, meskipun, bahwa jika anda melakukannya
df1['e'] = Series(np.random.randn(sLength), index=df1.index)
ini secara efektif akan menjadi kiri bergabung pada df1.indeks. Jadi jika anda ingin memiliki luar bergabung efek, saya mungkin tidak sempurna adalah solusi untuk membuat dataframe dengan nilai indeks yang meliputi alam semesta dari data anda, dan kemudian menggunakan kode di atas. Misalnya,
data = pd.DataFrame(index=all_possible_values)
df1['e'] = Series(np.random.randn(sLength), index=df1.index)
Sebelum menetapkan sebuah kolom baru, jika anda memiliki data diindeks, anda perlu memilah indeks. Setidaknya dalam kasus saya, saya harus:
data.set_index(['index_column'], inplace=True)
"if index is unsorted, assignment of a new column will fail"
data.sort_index(inplace = True)
data.loc['index_value1', 'column_y'] = np.random.randn(data.loc['index_value1', 'column_x'].shape[0])
Mari saya hanya menambahkan bahwa, seperti untuk hum3, .loc
didn't memecahkan SettingWithCopyWarning
dan aku harus resor untuk df.insert()
. Dalam kasus saya positif palsu yang dihasilkan oleh "palsu" rantai pengindeksan dict['a']['e']
, di mana 'e'
adalah kolom baru, dan dict['a']
adalah DataFrame yang datang dari kamus.
Perhatikan juga bahwa jika anda tahu apa yang anda lakukan, anda dapat beralih dari peringatan menggunakan
pd.pilihan.mode.chained_assignment = None
dan daripada menggunakan salah satu solusi lain yang diberikan di sini.
Saya sedang mencari sebuah cara umum untuk menambahkan kolom numpy.nan untuk dataframe tanpa mendapatkan bodoh
SettingWithCopyWarning`.
Dari yang berikut ini:
numpy
para Dwarves in-lineSaya datang dengan ini:
col = 'column_name'
df = df.assign(**{col:numpy.full(len(df), numpy.nan)})
untuk menyisipkan kolom baru pada lokasi tertentu (0 <= loc <= jumlah kolom) pada data frame, hanya menggunakan Dataframe.insert:
DataFrame.insert(loc, column, value)
Oleh karena itu, jika anda ingin menambahkan kolom e di ujung sebuah frame data yang disebut df, anda dapat menggunakan:
e = [-0.335485, -1.166658, -0.385571]
DataFrame.insert(loc=len(df.columns), column='e', value=e)
nilai dapat menjadi Seri, integer (dalam hal ini semua sel bisa diisi dengan satu nilai), atau sebuah array struktur seperti
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.insert.html
Demi kelengkapan - solusi lain menggunakan DataFrame.eval() metode:
Data:
In [44]: e
Out[44]:
0 1.225506
1 -1.033944
2 -0.498953
3 -0.373332
4 0.615030
5 -0.622436
dtype: float64
In [45]: df1
Out[45]:
a b c d
0 -0.634222 -0.103264 0.745069 0.801288
4 0.782387 -0.090279 0.757662 -0.602408
5 -0.117456 2.124496 1.057301 0.765466
7 0.767532 0.104304 -0.586850 1.051297
8 -0.103272 0.958334 1.163092 1.182315
9 -0.616254 0.296678 -0.112027 0.679112
Solusi:
In [46]: df1.eval("e = @e.values", inplace=True)
In [47]: df1
Out[47]:
a b c d e
0 -0.634222 -0.103264 0.745069 0.801288 1.225506
4 0.782387 -0.090279 0.757662 -0.602408 -1.033944
5 -0.117456 2.124496 1.057301 0.765466 -0.498953
7 0.767532 0.104304 -0.586850 1.051297 -0.373332
8 -0.103272 0.958334 1.163092 1.182315 0.615030
9 -0.616254 0.296678 -0.112027 0.679112 -0.622436