Pandaları kullanarak iki sütunu karşılaştırın


105

Bunu bir başlangıç ​​noktası olarak kullanmak:

a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

Out[8]: 
  one  two three
0   10  1.2   4.2
1   15  70   0.03
2    8   5     0

ifPandalar içinde bir ifade gibi bir şey kullanmak istiyorum .

if df['one'] >= df['two'] and df['one'] <= df['three']:
    df['que'] = df['one']

Temel olarak, her satırı ifade yoluyla kontrol edin if, yeni sütun oluşturun.

Dokümanlar kullanmamızı söylüyor .allama örnek yok ...


Eğer değer ne olmalı ififadedir False?
Alex Riley

3
@Merlin: Bir sütunda sayısal verileriniz varsa, en iyisi dizelerle karıştırmamaktır. Bunu yapmak, sütunun dtype değerini olarak değiştirir object. Bu, rastgele Python nesnelerinin sütunda depolanmasına izin verir, ancak daha yavaş sayısal hesaplama pahasına gelir. Bu nedenle, sütun sayısal verileri depoluyorsa, sayı olmayanlar için NaN'lerin kullanılması tercih edilir.
unutbu

1
Dizeleri olarak tamsayılar olması ve üzerlerinde karşılaştırma yapmaya çalışıyor tuhaf görünüyor: a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]. Bu "doğru" kod ile kafa karıştırıcı sonuçlar yaratır df['que'] = df['one'][(df['one'] >= df['two']) & (df['one'] <= df['three'])] verim 10o verim gerekirken, birinci hat için NaNgiriş olmuştur tamsayılar olurdu eğer.
Primer

Yanıtlar:


148

Np.where'i kullanabilirsiniz . Eğer condbir Boole dizidir ve Ave Bdaha sonra, diziler

C = np.where(cond, A, B)

C'yi Anerede condDoğru ve BNerede condYanlış'a eşit olarak tanımlar .

import numpy as np
import pandas as pd

a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

df['que'] = np.where((df['one'] >= df['two']) & (df['one'] <= df['three'])
                     , df['one'], np.nan)

verim

  one  two three  que
0  10  1.2   4.2   10
1  15   70  0.03  NaN
2   8    5     0  NaN

Birden fazla koşulunuz varsa, bunun yerine np.select'i kullanabilirsiniz . Örneğin, eğer arzu df['que']eşit df['two']zaman df['one'] < df['two']sonra,

conditions = [
    (df['one'] >= df['two']) & (df['one'] <= df['three']), 
    df['one'] < df['two']]

choices = [df['one'], df['two']]

df['que'] = np.select(conditions, choices, default=np.nan)

verim

  one  two three  que
0  10  1.2   4.2   10
1  15   70  0.03   70
2   8    5     0  NaN

Ne df['one'] >= df['two']zaman df['one'] < df['two']Yanlış olduğunu varsayabilirsek , koşullar ve seçimler basitleştirilebilir.

conditions = [
    df['one'] < df['two'],
    df['one'] <= df['three']]

choices = [df['two'], df['one']]

( NaN'ler varsa df['one']veya df['two']içeriyorsa varsayım doğru olmayabilir .)


Bunu not et

a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

dize değerlerine sahip bir DataFrame tanımlar. Sayısal göründükleri için, bu dizeleri kayan sayılara dönüştürmeniz daha iyi olabilir:

df2 = df.astype(float)

Ancak bu, sonuçları değiştirir, çünkü dizeler karakter karakter karşılaştırırken kayan sayılar sayısal olarak karşılaştırılır.

In [61]: '10' <= '4.2'
Out[61]: True

In [62]: 10 <= 4.2
Out[62]: False

73

.equalsSütunlar veya tüm veri çerçeveleri için kullanabilirsiniz .

df['col1'].equals(df['col2'])

Eşit iseler, bu ifade dönecektir True, aksi takdirde False.


22
Not: Bu yalnızca tüm sütunu diğeriyle karşılaştırır. Bu, columsn unsurunu akıllıca karşılaştırmaz
guerda

1
Bir sütunun her zaman diğer sütunlardan "büyük" veya "küçük" değerine sahip olup olmadığını görmek isteseniz nasıl olur?
rrlamichhane

28

Apply () kullanabilir ve bunun gibi bir şey yapabilirsiniz

df['que'] = df.apply(lambda x : x['one'] if x['one'] >= x['two'] and x['one'] <= x['three'] else "", axis=1)

veya lambda kullanmamayı tercih ederseniz

def que(x):
    if x['one'] >= x['two'] and x['one'] <= x['three']:
        return x['one']
    return ''
df['que'] = df.apply(que, axis=1)

2
Pandaların izin verdiği vektörleştirilmiş işlemlerden yararlanmadığından, bunun muhtemelen yayınlanan diğer yaklaşımlardan biraz daha yavaş olduğundan şüpheleniyorum.
Marius

@BobHaffner: karmaşık if / then / else ifadeleri kullanıldığında lambda okunamaz.
Merlin

@Merlin, başka bir şey ekleyebilirsiniz ve lambdas ve birden çok koşul konusunda sizinle aynı fikirdeyim
Bob Haffner

Lambda dışı işlevi, veri çerçevesi sütunlarını geçirip adı değiştirmeden geçirebileceğiniz şekilde genelleştirmenin bir yolu var mı?
AZhao

@AZhao iloc ile şu şekilde genelleme yapabilirsiniz df ['que'] = df.apply (lambda x: x.iloc [0] eğer x.iloc [0]> = x.iloc [1] ve x.iloc [0 ] <= x.iloc [2] else "", axis = 1) Demek istediğiniz bu mu? Açıkçası. sütunlarınızın sırası önemlidir
Bob Haffner

9

Bir yol, sütunu indekslemek için bir Boole serisi kullanmaktır df['one']. Bu size, Truegirişlerin aynı satırla aynı değere sahip olduğu df['one']ve Falsedeğerlerin olduğu yeni bir sütun verir NaN.

Boole dizisi sadece sizin ififadenizle verilir ( &bunun yerine kullanılması gerekli olmasına rağmen and):

>>> df['que'] = df['one'][(df['one'] >= df['two']) & (df['one'] <= df['three'])]
>>> df
    one two three   que
0   10  1.2 4.2      10
1   15  70  0.03    NaN
2   8   5   0       NaN

İsterseniz NaNdeğerleri diğer değerlerle değiştirilmesi için kullanabileceğiniz fillnayeni bir sütun üzerinde yöntemini que. 0Buradaki boş dize yerine kullandım :

>>> df['que'] = df['que'].fillna(0)
>>> df
    one two three   que
0   10  1.2   4.2    10
1   15   70  0.03     0
2    8    5     0     0

4

Her bir koşulu parantez içine alın ve ardından &koşulları birleştirmek için operatörü kullanın:

df.loc[(df['one'] >= df['two']) & (df['one'] <= df['three']), 'que'] = df['one']

Eşleşmeyi ~tersine çevirmek için yalnızca ("değil" operatörü) kullanarak eşleşmeyen satırları doldurabilirsiniz :

df.loc[~ ((df['one'] >= df['two']) & (df['one'] <= df['three'])), 'que'] = ''

Sen kullanmak gerekir &ve ~yerine andve notçünkü &ve ~operatörler iş eleman-eleman.

Nihai sonuç:

df
Out[8]: 
  one  two three que
0  10  1.2   4.2  10
1  15   70  0.03    
2   8    5     0  

1

np.selectVeri çerçevesinden kontrol edilecek birden fazla koşulunuz varsa ve farklı bir sütunda belirli bir seçim çıktığında kullanın

conditions=[(condition1),(condition2)]
choices=["choice1","chocie2"]

df["new column"]=np.select=(condtion,choice,default=)

Not: Koşulların ve seçeneklerin hiçbiri eşleşmemelidir, iki farklı koşul için aynı seçeneklere sahipseniz metni seçimde tekrarlayın


0

Bence OP'nin sezgisine en yakın olanın satır içi bir ifadesidir:

df['que'] = (df['one'] if ((df['one'] >= df['two']) and (df['one'] <= df['three'])) 

Kodunuz bana hata veriyordf['que'] = (df['one'] if ((df['one'] >= df['two']) and (df['one'] <= df['three'])) ^ SyntaxError: unexpected EOF while parsing
vasili111
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.