Pandalardan karmaşık ölçütlerle seçim yapma.


235

Örneğin ben basit DF var:

import pandas as pd
from random import randint

df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)],
                   'B': [randint(1, 9)*10 for x in xrange(10)],
                   'C': [randint(1, 9)*100 for x in xrange(10)]})

Pandaların yöntemlerini ve deyimlerini kullanarak 'B' için karşılık gelen değerlerin 50'den büyük olacağı ve 'C' için 900'e eşit olmayan 'A' dan değerler seçebilir miyim?


df.queryve pd.evalbu kullanım durumu için iyi uyuyor gibi görünüyor. pd.eval()İşlevler ailesi, özellikleri ve kullanım örnekleri hakkında bilgi için , lütfen pd.eval () kullanarak pandalarda Dinamik İfade Değerlendirme sayfasını ziyaret edin .
cs95

@Gecko'nun cevabını da kontrol edebilir: stackoverflow.com/questions/13611065/…
Nicholas Humphrey

Yanıtlar:


391

Elbette! Kurmak:

>>> import pandas as pd
>>> from random import randint
>>> df = pd.DataFrame({'A': [randint(1, 9) for x in range(10)],
                   'B': [randint(1, 9)*10 for x in range(10)],
                   'C': [randint(1, 9)*100 for x in range(10)]})
>>> df
   A   B    C
0  9  40  300
1  9  70  700
2  5  70  900
3  8  80  900
4  7  50  200
5  9  30  900
6  2  80  700
7  2  80  400
8  5  80  300
9  7  70  800

Sütun işlemlerini uygulayabilir ve boolean Serisi nesneleri alabiliriz:

>>> df["B"] > 50
0    False
1     True
2     True
3     True
4    False
5    False
6     True
7     True
8     True
9     True
Name: B
>>> (df["B"] > 50) & (df["C"] == 900)
0    False
1    False
2     True
3     True
4    False
5    False
6    False
7    False
8    False
9    False

[Yeni stile geçmek için güncelleme .loc]:

Ve sonra bunları nesneye indekslemek için kullanabiliriz. Okuma erişimi için dizinleri zincirleyebilirsiniz:

>>> df["A"][(df["B"] > 50) & (df["C"] == 900)]
2    5
3    8
Name: A, dtype: int64

ancak bir görünüm ile yazma erişimi için bunu yapan bir kopya arasındaki farktan dolayı kendinizi başınız belaya sokabilirsiniz. Bunun .locyerine şunları kullanabilirsiniz :

>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"]
2    5
3    8
Name: A, dtype: int64
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"].values
array([5, 8], dtype=int64)
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"] *= 1000
>>> df
      A   B    C
0     9  40  300
1     9  70  700
2  5000  70  900
3  8000  80  900
4     7  50  200
5     9  30  900
6     2  80  700
7     2  80  400
8     5  80  300
9     7  70  800

Yanlışlıkla yazdığımı == 900ve yazdığımı unutmayın != 900, ya da ~(df["C"] == 900)düzeltmek için çok tembelim. Okuyucu için egzersiz. : ^)


5
Hakkında .locgüncelleme - Bir kopyaya ve nerede bir görünüm elde nereye netleştirmek eğer iyi olurdu.
Gill Bates

3
panda veri çerçevesini filtrelemek ve OR operatörünü kullanmak mümkündür. Örneğin, bir sütun ayı olsaydı, df = data ['month' == JAN VEYA 'month' == FEB] diyebilir misiniz? Ve belki sorguyu daha karmaşık hale getiren ikinci bir sütun ekleyin, col_month = jan OR feb VE col_day = PAZARTESİ veya WENDNESDAY
yoshiserry 27:14

7
@yoshiserry: lütfen bunu ayrı bir soru olarak sorun. Burada eski bir cevabın yorumlarında kimse görmeyecek.
DSM

2
Parantezleri unutmayın - garip hatalar alırsınız{TypeError}cannot compare a dtyped [int64] array with a scalar of type [bool]
Mr_and_Mrs_D

Bu parantez kullanımı tüm seri üzerinde hesaplamalara yol açmaz mı? Verimlilik için tekrar tekrar alt kümelenmek istersek ne olur?
ifly6

56

Başka bir çözüm de sorgu yöntemini kullanmaktır :

import pandas as pd

from random import randint
df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)],
                   'B': [randint(1, 9) * 10 for x in xrange(10)],
                   'C': [randint(1, 9) * 100 for x in xrange(10)]})
print df

   A   B    C
0  7  20  300
1  7  80  700
2  4  90  100
3  4  30  900
4  7  80  200
5  7  60  800
6  3  80  900
7  9  40  100
8  6  40  100
9  3  10  600

print df.query('B > 50 and C != 900')

   A   B    C
1  7  80  700
2  4  90  100
4  7  80  200
5  7  60  800

Şimdi A sütunundaki döndürülen değerleri değiştirmek isterseniz dizinlerini kaydedebilirsiniz:

my_query_index = df.query('B > 50 & C != 900').index

.... ve .ilocdeğiştirmek için kullanın yani:

df.iloc[my_query_index, 0] = 5000

print df

      A   B    C
0     7  20  300
1  5000  80  700
2  5000  90  100
3     4  30  900
4  5000  80  200
5  5000  60  800
6     3  80  900
7     9  40  100
8     6  40  100
9     3  10  600

12

Ve parantez kullanmayı unutmayın!

Unutmayın &operatörü gibi operatörler üzerinden bir öncelik kazanır >ya <vs. Bu yüzden olduğunu

4 < 5 & 6 > 4

olarak değerlendirir False. Bu nedenle pd.loc, mantıksal ifadelerinizin yanına parantez koymanız gerekir, aksi takdirde bir hata alırsınız. Bu yüzden:

df.loc[(df['A'] > 10) & (df['B'] < 15)]

onun yerine

df.loc[df['A'] > 10 & df['B'] < 15]

hangi sonuçlanacak

TypeError: dtyped [float64] dizisini [bool] türündeki bir skalerle karşılaştıramazsınız


3

Karşılaştırma için bazı yerleşik işlevlere sahip pandaları kullanabilirsiniz. Dolayısıyla, "B" ve "C" koşullarının karşıladığı "A" değerlerini seçmek istiyorsanız (bir DataFrame pandaları nesnesini geri almak istediğinizi varsayarsak)

df[['A']][df.B.gt(50) & df.C.ne(900)]

df[['A']] DataFrame biçiminde A sütununu size geri verecektir.

pandaların 'gt' işlevi, B sütununun 50'den büyük konumlarını ve 'ne' 900'e eşit olmayan konumlarını döndürür.

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.