Panda - Dapatkan nilai baris pertama dari kolom yang diberikan

300

Ini sepertinya pertanyaan yang sangat mudah ... tapi saya tidak melihat jawaban mudah yang saya harapkan.

Jadi, bagaimana saya mendapatkan nilai di baris ke-n dari kolom yang diberikan di Panda? (Saya terutama tertarik pada baris pertama, tetapi akan tertarik pada praktik yang lebih umum juga).

Sebagai contoh, katakanlah saya ingin menarik nilai 1.2 dalam Btime sebagai variabel.

Apa cara yang tepat untuk melakukan ini?

df_test =

  ATime   X   Y   Z   Btime  C   D   E
0    1.2  2  15   2    1.2  12  25  12
1    1.4  3  12   1    1.3  13  22  11
2    1.5  1  10   6    1.4  11  20  16
3    1.6  2   9  10    1.7  12  29  12
4    1.9  1   1   9    1.9  11  21  19
5    2.0  0   0   0    2.0   8  10  11
6    2.4  0   0   0    2.4  10  12  15
Ahmed Haque
sumber
7
Jika Anda hanya ingin baris pertama lalu df_test.head(1)bekerja, bentuk yang lebih umum adalah menggunakan ilocseperti yang dijawab oleh unutbu
EdChum
1
Apakah Anda hanya menginginkan nilainya 1.2? atau Seri panjang 1 yang Anda dapatkan df_test.head(1), yang juga akan berisi indeks? Untuk mendapatkan nilai saja df_test.head(1).item(), atau tolist()kemudian iris.
smci

Jawaban:

472

Untuk memilih ithbaris, gunakaniloc :

In [31]: df_test.iloc[0]
Out[31]: 
ATime     1.2
X         2.0
Y        15.0
Z         2.0
Btime     1.2
C        12.0
D        25.0
E        12.0
Name: 0, dtype: float64

Untuk memilih nilai engan di Btimekolom yang dapat Anda gunakan:

In [30]: df_test['Btime'].iloc[0]
Out[30]: 1.2

Ada perbedaan antara df_test['Btime'].iloc[0](disarankan) dan df_test.iloc[0]['Btime']:

DataFrames menyimpan data dalam blok berbasis kolom (di mana setiap blok memiliki dtype tunggal). Jika Anda memilih berdasarkan kolom terlebih dahulu, tampilan dapat dikembalikan (yang lebih cepat daripada mengembalikan salinan) dan tipe asli dipertahankan. Sebaliknya, jika Anda memilih berdasarkan baris terlebih dahulu, dan jika DataFrame memiliki kolom dengan tipe yang berbeda, maka Pandas menyalin data ke dalam Seri objek objek yang baru. Jadi memilih kolom sedikit lebih cepat daripada memilih baris. Jadi, meskipun df_test.iloc[0]['Btime']berfungsi, df_test['Btime'].iloc[0]sedikit lebih efisien.

Ada perbedaan besar antara keduanya dalam hal penugasan. df_test['Btime'].iloc[0] = xmempengaruhi df_test, tetapi df_test.iloc[0]['Btime'] mungkin tidak. Lihat di bawah untuk penjelasan mengapa. Karena perbedaan halus dalam urutan pengindeksan membuat perbedaan besar dalam perilaku, lebih baik menggunakan tugas pengindeksan tunggal:

df.iloc[0, df.columns.get_loc('Btime')] = x

df.iloc[0, df.columns.get_loc('Btime')] = x (disarankan):

Cara yang disarankan untuk menetapkan nilai baru ke DataFrame adalah untuk menghindari pengindeksan berantai , dan alih-alih menggunakan metode yang ditunjukkan oleh andrew ,

df.loc[df.index[n], 'Btime'] = x

atau

df.iloc[n, df.columns.get_loc('Btime')] = x

Metode yang terakhir ini sedikit lebih cepat, karena df.locharus mengonversi label baris dan kolom ke indeks posisi, jadi ada sedikit konversi yang diperlukan jika Anda menggunakannya df.iloc.


df['Btime'].iloc[0] = x berfungsi, tetapi tidak disarankan:

Meskipun ini berfungsi, ini mengambil keuntungan dari cara DataFrames saat ini diterapkan. Tidak ada jaminan bahwa Panda harus bekerja seperti ini di masa depan. Secara khusus, ia mengambil keuntungan dari fakta bahwa (saat ini) df['Btime']selalu mengembalikan tampilan (bukan salinan) sehingga df['Btime'].iloc[n] = xdapat digunakan untuk menetapkan nilai baru di lokasi ke-n Btimekolom df.

Karena Pandas tidak membuat jaminan eksplisit tentang kapan pengindeks mengembalikan tampilan versus salinan, tugas yang menggunakan pengindeksan berantai umumnya selalu menaikkan SettingWithCopyWarningmeskipun dalam kasus ini tugas berhasil memodifikasi df:

In [22]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [24]: df['bar'] = 100
In [25]: df['bar'].iloc[0] = 99
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self._setitem_with_indexer(indexer, value)

In [26]: df
Out[26]: 
  foo  bar
0   A   99  <-- assignment succeeded
2   B  100
1   C  100

df.iloc[0]['Btime'] = x tidak bekerja:

Sebaliknya, tugas dengan df.iloc[0]['bar'] = 123tidak berfungsi karena df.iloc[0]mengembalikan salinan:

In [66]: df.iloc[0]['bar'] = 123
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

In [67]: df
Out[67]: 
  foo  bar
0   A   99  <-- assignment failed
2   B  100
1   C  100

Peringatan : Saya sebelumnya menyarankan df_test.ix[i, 'Btime']. Tetapi ini tidak dijamin memberi Anda ithnilai karena ixmencoba mengindeks dengan label sebelum mencoba mengindeks berdasarkan posisi . Jadi jika DataFrame memiliki indeks integer yang tidak diurutkan mulai dari 0, maka menggunakan ix[i]akan mengembalikan baris berlabel i daripada ithbaris. Sebagai contoh,

In [1]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])

In [2]: df
Out[2]: 
  foo
0   A
2   B
1   C

In [4]: df.ix[1, 'foo']
Out[4]: 'C'
unutbu
sumber
1
@CristianCiupitu: DataFrames menyimpan data dalam blok berbasis kolom (di mana setiap blok memiliki dtype tunggal). Jika Anda memilih berdasarkan kolom terlebih dahulu, tampilan dapat dikembalikan (yang lebih cepat daripada mengembalikan salinan) dan dtype asli dipertahankan. Sebaliknya, jika Anda memilih berdasarkan baris terlebih dahulu, dan jika DataFrame memiliki kolom dengan tipe yang berbeda, maka Pandas menyalin data ke dalam Seri objek objek yang baru. Jadi memilih kolom sedikit lebih cepat daripada memilih baris. Jadi, meskipun df_test.iloc[0]['Btime']berfungsi, df_test.iloc['Btime'][0]sedikit lebih efisien.
unutbu
@unutbu, df['Btime'].iloc[0]lebih disukai df['Btime'].values[0]? saya dapat melihat dari dokumentasi yang berbunyi "Peringatan: Kami sarankan menggunakan Series.array atau Series.to_numpy (), tergantung pada apakah Anda memerlukan referensi ke data yang mendasarinya atau array NumPy." tapi saya tidak yakin apa artinya itu
aydow
28

Perhatikan bahwa jawaban dari @unutbu akan benar hingga Anda ingin menetapkan nilai ke sesuatu yang baru, maka itu tidak akan berfungsi jika dataframe Anda adalah tampilan.

In [4]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [5]: df['bar'] = 100
In [6]: df['bar'].iloc[0] = 99
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas-0.16.0_19_g8d2818e-py2.7-macosx-10.9-x86_64.egg/pandas/core/indexing.py:118: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self._setitem_with_indexer(indexer, value)

Pendekatan lain yang secara konsisten akan bekerja dengan pengaturan dan pengambilan adalah:

In [7]: df.loc[df.index[0], 'foo']
Out[7]: 'A'
In [8]: df.loc[df.index[0], 'bar'] = 99
In [9]: df
Out[9]:
  foo  bar
0   A   99
2   B  100
1   C  100
andrew
sumber
1
Saya mengulang-ulang sekelompok file .csv dan membaca nilai pertama dari kolom tertentu di masing-masing. Untuk beberapa alasan yang saya tidak dapat menjelaskan alih-alih mengembalikan nilai ini terkadang mengembalikan indeks bersama dengan nilai yang mengacaukan pemrosesan. Saya menggunakan df.col.unique () [0].
sparrow
15

Cara lain untuk melakukan ini:

first_value = df['Btime'].values[0]

Cara ini tampaknya lebih cepat daripada menggunakan .iloc:

In [1]: %timeit -n 1000 df['Btime'].values[20]
5.82 µs ± 142 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [2]: %timeit -n 1000 df['Btime'].iloc[20]
29.2 µs ± 1.28 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Abdulrahman Bres
sumber
12
  1. df.iloc[0].head(1) - Kumpulan data pertama hanya dari seluruh baris pertama.
  2. df.iloc[0] - Seluruh baris pertama di kolom.
nikhil
sumber
8

Secara umum, jika Anda ingin mengambil baris N pertama dari kolom J dari pandas dataframecara terbaik untuk melakukan ini adalah:

data = dataframe[0:N][:,J]
anis
sumber
2
@anis: Untuk tujuan ini, Anda sebaiknya menulis pertanyaan baru dengan meminta solusi yang lebih umum dan menjawabnya sendiri, saya percaya.
jonathan.scholbach
3

Untuk mendapatkan misalnya nilai dari kolom 'test' dan baris 1 berfungsi seperti itu

df[['test']].values[0][0]

karena hanya df[['test']].values[0]mengembalikan array

Alex Ortner
sumber
1

Cara lain untuk mendapatkan baris pertama dan mempertahankan indeks:

x = df.first('d') # Returns the first day. '3d' gives first three days.
Hunaphu
sumber