Saya telah membuat Pandas DataFrame
df = DataFrame(index=['A','B','C'], columns=['x','y'])
dan mendapatkan ini
x y A NaN NaN B NaN NaN NaN C NaN NaN NaN
x y A NaN NaN NaN B NaN NaN NaN C 10 NaN
dengan kode ini:
df.xs('C')['x'] = 10
tetapi isi dari df
belum berubah. Sekali lagi hanya NaN
di DataFrame.
Ada saran?
RukTech's answer, df.set_value('C', 'x', 10)
, jauh lebih cepat daripada opsi yang saya sarankan di bawah ini. Namun, opsi ini telah ditetapkan untuk tidak digunakan lagi.
Untuk ke depannya, metode yang direkomendasikan adalah .iat/.at
.
Mengapa df.xs('C')['x']=10
tidak bekerja:
df.xs('C')
secara default, mengembalikan dataframe baru dengan salinan dari data, jadi
df.xs('C')['x']=10
memodifikasi dataframe baru ini saja.
df['x']
mengembalikan tampilan dari dataframe df
, jadi
df['x']['C'] = 10
memodifikasi df
itu sendiri.
Peringatan: Kadang-kadang sulit untuk memprediksi apakah sebuah operasi mengembalikan salinan atau tampilan. Untuk alasan ini docs merekomendasikan untuk menghindari penugasan dengan "chained indexing".
Jadi alternatif yang direkomendasikan adalah
df.at['C', 'x'] = 10
yang melakukan modifikasi df
.
In [18]: %timeit df.set_value('C', 'x', 10)
100000 loops, best of 3: 2.9 µs per loop
In [20]: %timeit df['x']['C'] = 10
100000 loops, best of 3: 6.31 µs per loop
In [81]: %timeit df.at['C', 'x'] = 10
100000 loops, best of 3: 9.2 µs per loop
Update: Metode .set_value
akan tidak digunakan lagi. .iat/.at
adalah pengganti yang baik, sayangnya pandas menyediakan sedikit dokumentasi
Cara tercepat untuk melakukan ini adalah menggunakan set_value. Metode ini ~100 kali lebih cepat dari metode .ix
. Sebagai contoh:
df.set_value('C', 'x', 10)
Anda juga dapat menggunakan bersyarat lookup menggunakan .loc
seperti yang terlihat berikut ini:
df.loc[df[<some_column_name>] == <condition>, [<another_column_name>]] = <value_to_add>
di mana <some_column_name
adalah kolom yang ingin anda periksa <kondisi>
terhadap variabel dan <another_column_name>
adalah kolom yang ingin anda tambahkan (dapat berupa sebuah kolom baru atau yang sudah ada). <value_to_add>
adalah nilai yang ingin anda tambahkan ke bahwa kolom/baris.
Contoh ini doesn't bekerja justru dengan pertanyaan di tangan, tapi mungkin berguna bagi seseorang yang ingin menambah nilai tertentu berdasarkan suatu kondisi.
Cara yang direkomendasikan (menurut para pengelola) untuk menetapkan nilai adalah:
df.ix['x','C']=10
Menggunakan 'chained indexing' (df['x']['C']
) dapat menyebabkan masalah.
Lihat:
.iat/.di
adalah solusi yang baik.
Seandainya anda memiliki sederhana ini data_frame:
A B C
0 1 8 4
1 3 9 6
2 22 33 52
jika kita ingin mengubah nilai dari cell [0,"A"]
u dapat menggunakan salah satu dari mereka solusi :
df.iat[0,0] = 2
df.pada[0,'A'] = 2
Dan di sini adalah contoh lengkap cara menggunakan iat
untuk mendapatkan dan menetapkan nilai dari cell :
def prepossessing(df):
for index in range(0,len(df)):
df.iat[index,0] = df.iat[index,0] * 2
return df
y_train sebelum :
0
0 54
1 15
2 15
3 8
4 31
5 63
6 11
y_train setelah memanggil menawan fungsi yang iat
untuk mengubah kalikan nilai dari masing-masing sel dengan 2:
0
0 108
1 30
2 30
3 16
4 62
5 126
6 22
anda dapat menggunakan .iloc
.
df.iloc[[2], [0]] = 10
set_value()
sudah ditinggalkan.
Mulai dari rilis 0.23.4, Panda "mengumumkan masa depan"...
>>> df
Cars Prices (U$)
0 Audi TT 120.0
1 Lamborghini Aventador 245.0
2 Chevrolet Malibu 190.0
>>> df.set_value(2, 'Prices (U$)', 240.0)
__main__:1: FutureWarning: set_value is deprecated and will be removed in a future release.
Please use .at[] or .iat[] accessors instead
Cars Prices (U$)
0 Audi TT 120.0
1 Lamborghini Aventador 245.0
2 Chevrolet Malibu 240.0
Mempertimbangkan saran ini, di sini's demonstrasi cara menggunakannya:
>>> df.iat[1, 1] = 260.0
>>> df
Cars Prices (U$)
0 Audi TT 120.0
1 Lamborghini Aventador 260.0
2 Chevrolet Malibu 240.0
>>> df.at[2, "Cars"] = "Chevrolet Corvette"
>>> df
Cars Prices (U$)
0 Audi TT 120.0
1 Lamborghini Aventador 260.0
2 Chevrolet Corvette 240.0
Referensi:
Berikut ini adalah ringkasan berlaku solusi yang ditawarkan oleh semua pengguna, untuk data frame yang diindeks oleh integer dan string.
df.iloc, df.loc dan df.bekerja untuk kedua jenis data frame, df.iloc hanya bekerja dengan baris/kolom integer indeks, df.loc dan df.pada mendukung untuk menetapkan nilai-nilai yang menggunakan nama kolom dan / atau integer indeks.
Ketika indeks tertentu tidak ada, kedua df.loc dan df.di akan menambahkan yang baru dimasukkan baris/kolom yang sudah ada data frame, tapi df.iloc akan meningkatkan "IndexError: posisi pengindeks yang out-of-bounds". Contoh kerja diuji di Python 2.7 dan 3.7 adalah sebagai berikut:
import numpy as np, pandas as pd
df1 = pd.DataFrame(index=np.arange(3), columns=['x','y','z'])
df1['x'] = ['A','B','C']
df1.at[2,'y'] = 400
# rows/columns specified does not exist, appends new rows/columns to existing data frame
df1.at['D','w'] = 9000
df1.loc['E','q'] = 499
# using df[<some_column_name>] == <condition> to retrieve target rows
df1.at[df1['x']=='B', 'y'] = 10000
df1.loc[df1['x']=='B', ['z','w']] = 10000
# using a list of index to setup values
df1.iloc[[1,2,4], 2] = 9999
df1.loc[[0,'D','E'],'w'] = 7500
df1.at[[0,2,"D"],'x'] = 10
df1.at[:, ['y', 'w']] = 8000
df1
>>> df1
x y z w q
0 10 8000 NaN 8000 NaN
1 B 8000 9999 8000 NaN
2 10 8000 9999 8000 NaN
D 10 8000 NaN 8000 NaN
E NaN 8000 9999 8000 499.0
Aku diuji dan output adalah df.set_value
adalah sedikit lebih cepat, tetapi metode resmi df.di
terlihat seperti tercepat non usang cara untuk melakukannya.
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.rand(100, 100))
%timeit df.iat[50,50]=50 # ✓
%timeit df.at[50,50]=50 # ✔
%timeit df.set_value(50,50,50) # will deprecate
%timeit df.iloc[50,50]=50
%timeit df.loc[50,50]=50
7.06 µs ± 118 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
5.52 µs ± 64.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
3.68 µs ± 80.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
98.7 µs ± 1.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
109 µs ± 1.42 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Catatan ini adalah menetapkan nilai untuk sel tunggal. Untuk vektor-vektor loc
dan iloc
harus menjadi pilihan yang lebih baik karena mereka vectorized.
df.loc['c','x']=10
Ini akan mengubah nilai cth berturut-turut dan
xth kolom.
Selain jawaban di atas, berikut adalah acuan membandingkan cara-cara yang berbeda untuk menambahkan baris data yang sudah ada dataframe. Hal ini menunjukkan bahwa menggunakan atau mengatur-nilai adalah cara yang paling efisien untuk besar dataframes (setidaknya untuk tes ini kondisi).
Untuk tes ini, yang ada dataframe yang terdiri dari 100,000 baris dan 1.000 kolom dan acak numpy nilai-nilai yang digunakan. Ini dataframe, 100 baris baru ditambahkan.
Kode lihat di bawah ini:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 21 16:38:46 2018
@author: gebbissimo
"""
import pandas as pd
import numpy as np
import time
NUM_ROWS = 100000
NUM_COLS = 1000
data = np.random.rand(NUM_ROWS,NUM_COLS)
df = pd.DataFrame(data)
NUM_ROWS_NEW = 100
data_tot = np.random.rand(NUM_ROWS + NUM_ROWS_NEW,NUM_COLS)
df_tot = pd.DataFrame(data_tot)
DATA_NEW = np.random.rand(1,NUM_COLS)
#%% FUNCTIONS
# create and append
def create_and_append(df):
for i in range(NUM_ROWS_NEW):
df_new = pd.DataFrame(DATA_NEW)
df = df.append(df_new)
return df
# create and concatenate
def create_and_concat(df):
for i in range(NUM_ROWS_NEW):
df_new = pd.DataFrame(DATA_NEW)
df = pd.concat((df, df_new))
return df
# store as dict and
def store_as_list(df):
lst = [[] for i in range(NUM_ROWS_NEW)]
for i in range(NUM_ROWS_NEW):
for j in range(NUM_COLS):
lst[i].append(DATA_NEW[0,j])
df_new = pd.DataFrame(lst)
df_tot = df.append(df_new)
return df_tot
# store as dict and
def store_as_dict(df):
dct = {}
for j in range(NUM_COLS):
dct[j] = []
for i in range(NUM_ROWS_NEW):
dct[j].append(DATA_NEW[0,j])
df_new = pd.DataFrame(dct)
df_tot = df.append(df_new)
return df_tot
# preallocate and fill using .at
def fill_using_at(df):
for i in range(NUM_ROWS_NEW):
for j in range(NUM_COLS):
#print("i,j={},{}".format(i,j))
df.at[NUM_ROWS+i,j] = DATA_NEW[0,j]
return df
# preallocate and fill using .at
def fill_using_set(df):
for i in range(NUM_ROWS_NEW):
for j in range(NUM_COLS):
#print("i,j={},{}".format(i,j))
df.set_value(NUM_ROWS+i,j,DATA_NEW[0,j])
return df
#%% TESTS
t0 = time.time()
create_and_append(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))
t0 = time.time()
create_and_concat(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))
t0 = time.time()
store_as_list(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))
t0 = time.time()
store_as_dict(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))
t0 = time.time()
fill_using_at(df_tot)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))
t0 = time.time()
fill_using_set(df_tot)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))
Salah satu cara untuk menggunakan indeks dengan kondisi pertama mendapatkan indeks dari semua baris yang memenuhi kondisi anda dan kemudian hanya menggunakan orang-orang turut dalam berbagai beberapa cara
conditional_index = df.loc[ df['col nama'] <kondisi> ].indeks
Kemudian anda dapat menggunakan ini turut indeks dalam berbagai cara seperti
Mengganti nilai dari satu kolom untuk conditional_index
df.loc[conditional_index , [col name]]= <nilai baru>
Mengganti nilai dari beberapa kolom untuk conditional_index
df.loc[conditional_index, [col1,col2]]= <nilai baru>
Salah satu manfaat menyimpan conditional_index adalah bahwa anda dapat menetapkan nilai dari satu kolom ke kolom lain dengan indeks baris yang sama
df.loc[conditional_index, [col1,col2]]= df.loc[conditional_index,'col nama']
Ini semua dimungkinkan karena .indeks mengembalikan sebuah array dari index yang .loc dapat digunakan dengan pengalamatan langsung sehingga menghindari traversals lagi dan lagi.
Dari versi 0.21.1 anda juga dapat menggunakan .pada
metode. Ada beberapa perbedaan dibandingkan dengan .loc
seperti yang disebutkan di sini - https://stackoverflow.com/questions/37216485/pandas-at-versus-loc tapi itu's lebih cepat pada nilai tunggal pengganti
Saya juga sedang mencari topik ini dan saya menempatkan bersama-sama cara untuk iterate melalui DataFrame dan update dengan pencarian nilai-nilai dari kedua DataFrame. Berikut ini adalah kode saya.
src_df = pd.read_sql_query(src_sql,src_connection)
for index1, row1 in src_df.iterrows():
for index, row in vertical_df.iterrows():
src_df.set_value(index=index1,col=u'etl_load_key',value=etl_load_key)
if (row1[u'src_id'] == row['SRC_ID']) is True:
src_df.set_value(index=index1,col=u'vertical',value=row['VERTICAL'])