Koşullu Değiştirme Pandaları


123

Bir DataFrame'im var ve belirli bir sütundaki değerleri sıfır ile aşan değerleri değiştirmek istiyorum. Bunu başarmanın bir yolu olduğunu düşünmüştüm:

df[df.my_channel > 20000].my_channel = 0

Kanalı yeni bir veri çerçevesine kopyalarsam çok basit:

df2 = df.my_channel 

df2[df2 > 20000] = 0

Bu tam olarak istediğimi yapıyor, ancak orijinal DataFrame'in bir parçası olarak kanalla çalışmıyor gibi görünüyor.


Burada aradığınızı düşündüğüm şeyi buldum .
ayak ıslat

Yanıtlar:


181

.ixdizinleyici, 0.20.0'dan önceki pandalar sürümünde sorunsuz çalışır, ancak pandalar 0.20.0'dan beri, .ixdizinleyici kullanımdan kaldırılmıştır , bu nedenle kullanmaktan kaçınmalısınız. Bunun yerine, .locveya ilocdizinleyicileri kullanabilirsiniz . Bu sorunu şu şekilde çözebilirsiniz:

mask = df.my_channel > 20000
column_name = 'my_channel'
df.loc[mask, column_name] = 0

Veya tek satırda

df.loc[df.my_channel > 20000, 'my_channel'] = 0

maskhangi satırları seçmek için yardımcı olur df.my_channel > 20000ise Trueederken, df.loc[mask, column_name] = 0seçilen satırlara setleri değeri 0 nerede maskadıdır sütununda tutar column_name.

Güncelleme: Bu durumda kullanmalısınız locçünkü kullanırsanız iloc, iLocation tabanlı bir tamsayı türünde mantıksal indekslemenin mevcutNotImplementedError olmadığını söyleyeceksiniz .


82

Deneyin

df.loc[df.my_channel > 20000, 'my_channel'] = 0

Not: v0.20.0'dan ix beri , loc/ lehine kullanımdan kaldırılmıştıriloc .


8
Teşekkür ederim. Ben de kendi çözümümü buldum, şuydu: df.my_channel [df.my_channel> 20000] = 0
BMichell

2
@BMichell Bence çözümünüz 0.13'te size uyarılar vermeye başlayabilir, henüz deneme şansı olmadı
lowtech

verim hatası: /opt/anaconda3/envs/python35/lib/python3.5/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning: DataFrame'den bir dilim kopyası üzerinde bir değer ayarlanmaya çalışılıyor. dokümantasyon: pandas.pydata.org/pandas-docs/stable/… "" "Bir IPython çekirdeği başlatmak için giriş noktası.
Rutger Hofste

@RutgerHofste bundan bahsettiğiniz için teşekkürler, ancak başka bir argüman asla Python3 kullanmıyor
lowtech

34

np.where işlevi aşağıdaki gibi çalışır:

df['X'] = np.where(df['Y']>=50, 'yes', 'no')

Senin durumunda isteyeceksin:

import numpy as np
df['my_channel'] = np.where(df.my_channel > 20000, 0, df.my_channel)

19

Orijinal veri çerçevenizin güncellenmemesinin nedeni, zincirleme dizinlemenin , veri çerçevenizin bir görünümü yerine bir kopyayı değiştirmenize neden olabilmesidir. Docs bu tavsiyelerde:

Bir panda nesnesindeki değerleri ayarlarken, zincirleme indeksleme denen şeyden kaçınmak için özen gösterilmelidir.

Birkaç seçeneğiniz var: -

loc + Boole endeksleme

loc değerleri ayarlamak için kullanılabilir ve Boole maskelerini destekler:

df.loc[df['my_channel'] > 20000, 'my_channel'] = 0

mask + Boole endeksleme

Serinize şunları atayabilirsiniz:

df['my_channel'] = df['my_channel'].mask(df['my_channel'] > 20000, 0)

Veya dizinizi yerinde güncelleyebilirsiniz:

df['my_channel'].mask(df['my_channel'] > 20000, 0, inplace=True)

np.where + Boole endeksleme

Sen edebilirsiniz durumunuz edilir orijinal dizi atayarak numpy kullanmak değil memnun; ancak, ilk iki çözüm, yalnızca belirtilen değerleri açıkça değiştirdikleri için daha temizdir.

df['my_channel'] = np.where(df['my_channel'] > 20000, 0, df['my_channel'])

0

lambdaFonksiyonu şöyle Seriesbir DataFrameşunun üzerinde kullanırdım :

f = lambda x: 0 if x>100 else 1
df['my_column'] = df['my_column'].map(f)

Bunun verimli bir yol olduğunu iddia etmiyorum ama iyi çalışıyor.


3
Bu verimsizdir ve satır bazında bir işlemde Python düzeyinde bir döngü içerdiğinden önerilmez.
jpp

Teşekkür ederim, sanırım locburada kullanabiliriz df.loc[: , 'my_column'] = df['my_column'].map(f). Aşağıda ekledikleriniz gibi hızlı mı bilmiyorum.
Özkan Serttas

2
Hayır, sütun bazında değil de satır bazında çalıştığınız için hala yavaş.
jpp

0

Bunu dene:

df.my_channel = df.my_channel.where(df.my_channel <= 20000, other= 0)

veya

df.my_channel = df.my_channel.mask(df.my_channel > 20000, other= 0)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.