Bagaimana cara memilih baris dalam DataFrame antara dua nilai, dengan Python Pandas?

102

Saya mencoba mengubah DataFrame dfagar hanya berisi baris yang nilai dalam kolomnya closing_priceantara 99 dan 101 dan mencoba melakukan ini dengan kode di bawah ini.

Namun, saya mendapatkan kesalahannya

ValueError: Nilai kebenaran dari suatu Seri tidak jelas. Gunakan a.empty, a.bool (), a.item (), a.any () atau a.all ()

dan saya ingin tahu apakah ada cara untuk melakukan ini tanpa menggunakan loop.

df = df[(99 <= df['closing_price'] <= 101)]
pengguna131983
sumber
Masalahnya di sini adalah bahwa Anda tidak dapat membandingkan skalar dengan array, maka kesalahannya, untuk perbandingan Anda harus menggunakan operator bitwise dan menyertakannya dalam tanda kurung karena prioritas operator
EdChum
df.querydan pd.evalsepertinya cocok untuk kasus penggunaan ini. Untuk informasi tentang pd.eval()keluarga fungsi, fitur dan kasus penggunaannya, silakan kunjungi Evaluasi Ekspresi Dinamis di pandas menggunakan pd.eval () .
cs95

Jawaban:

108

Anda harus menggunakan ()untuk mengelompokkan vektor boolean Anda untuk menghilangkan ambiguitas.

df = df[(df['closing_price'] >= 99) & (df['closing_price'] <= 101)]
Jianxun Li
sumber
177

Perhatikan juga rangkaian antara :

df = df[df['closing_price'].between(99, 101)]
Parfait
sumber
6
Opsi inclusive=Truedigunakan secara default di between, sehingga Anda dapat melakukan kueri seperti inidf = df[df['closing_price'].between(99, 101)]
Anton Ermakov
3
ini jawaban terbaik! kerja bagus!
PEBKAC
Apakah ada fungsi "tidak di antara" di panda? Saya tidak menemukannya.
dsugasa
3
@dsugasa, gunakan operator tilde dengan between.
Parfait
1
@dsugasa misalnyadf = df[~df['closing_price'].between(99, 101)]
Jan33
23

ada alternatif yang lebih bagus - gunakan metode query () :

In [58]: df = pd.DataFrame({'closing_price': np.random.randint(95, 105, 10)})

In [59]: df
Out[59]:
   closing_price
0            104
1             99
2             98
3             95
4            103
5            101
6            101
7             99
8             95
9             96

In [60]: df.query('99 <= closing_price <= 101')
Out[60]:
   closing_price
1             99
5            101
6            101
7             99

UPDATE: menjawab komentar:

Saya suka sintaks di sini tetapi gagal saat mencoba menggabungkan dengan ekspresi; df.query('(mean + 2 *sd) <= closing_price <=(mean + 2 *sd)')

In [161]: qry = "(closing_price.mean() - 2*closing_price.std())" +\
     ...:       " <= closing_price <= " + \
     ...:       "(closing_price.mean() + 2*closing_price.std())"
     ...:

In [162]: df.query(qry)
Out[162]:
   closing_price
0             97
1            101
2             97
3             95
4            100
5             99
6            100
7            101
8             99
9             95
MaxU
sumber
Saya suka sintaks di sini tetapi gagal saat mencoba menggabungkan dengan ekspresi; df.query ('(mean + 2 * sd) <= closing_price <= (mean + 2 * sd)')
memetakan dom
1
@mappingdom, apa itu meandan sd? Apakah itu nama kolom?
MaxU
tidak, mereka adalah rata-rata yang dihitung dan deviasi standar yang disimpan sebagai float
mapping dom
@mappingdom, apa maksudmu mengatakan "disimpan"?
MaxU
@mappingdom, saya telah memperbarui posting saya - apakah itu yang Anda minta?
MaxU
9

Anda juga bisa menggunakan .between()metode

emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv")

emp[emp["Salary"].between(60000, 61000)]

Keluaran

masukkan deskripsi gambar di sini

Riz.Khan
sumber
7
newdf = df.query('closing_price.mean() <= closing_price <= closing_price.std()')

atau

mean = closing_price.mean()
std = closing_price.std()

newdf = df.query('@mean <= closing_price <= @std')
crashMOGWAI
sumber
3

Jika Anda berurusan dengan banyak nilai dan beberapa masukan, Anda juga dapat mengatur fungsi terapan seperti ini. Dalam hal ini memfilter kerangka data untuk lokasi GPS yang termasuk dalam rentang tertentu.

def filter_values(lat,lon):
    if abs(lat - 33.77) < .01 and abs(lon - -118.16) < .01:
        return True
    elif abs(lat - 37.79) < .01 and abs(lon - -122.39) < .01:
        return True
    else:
        return False


df = df[df.apply(lambda x: filter_values(x['lat'],x['lon']),axis=1)]
burung gereja
sumber
1

Bukan ini

df = df[(99 <= df['closing_price'] <= 101)]

Anda harus menggunakan ini

df = df[(df['closing_price']>=99 ) & (df['closing_price']<=101)]

Kita harus menggunakan operator Logika bitwise NumPy |, &, ~, ^ untuk kueri penggabungan. Selain itu, tanda kurung penting untuk prioritas operator.

Untuk info lebih lanjut, Anda dapat mengunjungi link: Comparisons, Masks, dan Boolean Logic

Rushabh Agarwal
sumber