Pandalar veri çerçevelerini birden çok sütuna göre nasıl filtreleyebilirsiniz?


103

Bir veri çerçevesini (df) tek bir sütuna göre filtrelemek için, verileri erkek ve kadınlarla birlikte ele alırsak şunları yapabiliriz:

males = df[df[Gender]=='Male']

Soru 1 - Peki ya veriler birkaç yıla yayılmışsa ve ben 2014 için yalnızca erkekleri görmek istersem?

Diğer dillerde şöyle bir şey yapabilirim:

if A = "Male" and if B = "2014" then 

(Bunu yapmak ve yeni bir veri çerçevesi nesnesinde orijinal veri çerçevesinin bir alt kümesini almak istemem dışında)

Soru 2. Bunu bir döngü içinde nasıl yapabilirim ve her benzersiz yıl ve cinsiyet kümesi için bir veri çerçevesi nesnesi oluşturabilirim (ör: 2013-Erkek, 2013-Kadın, 2014-Erkek ve 2014-Kadın için bir df

for y in year:

for g in gender:

df = .....

Eğer istiyor musunuz filtrelemek onu ya grup bunu? Her benzersiz yıl ve cinsiyet kümesi için ayrı bir DataFrame oluşturmak istiyorsanız, bakın groupby.
BrenBarn

1
Bu cevap , pandalardaki mantıksal indeksleme ve mantıksal operatörler hakkında kapsamlı bir genel bakış sağlar.
cs95

Yanıtlar:


185

&Operatörü kullanarak , alt ifadeleri şunlarla sarmayı unutmayın ():

males = df[(df[Gender]=='Male') & (df[Year]==2014)]

Veri çerçevelerinizi dictfor döngüsü kullanarak depolamak için :

from collections import defaultdict
dic={}
for g in ['male', 'female']:
  dic[g]=defaultdict(dict)
  for y in [2013, 2014]:
    dic[g][y]=df[(df[Gender]==g) & (df[Year]==y)] #store the DataFrames to a dict of dict

DÜZENLE:

Sizin için bir demo getDF:

def getDF(dic, gender, year):
  return dic[gender][year]

print genDF(dic, 'male', 2014)

harika cevap zhangxaochen - cevabınızı, veri çerçevelerini oluşturan (yıl ve cinsiyet verileriyle) bir for döngüsünü nasıl yapabileceğinizi en altta gösterecek şekilde düzenleyebilir misiniz? def GetDF (dikte, anahtar): dönüş dict [anahtar]
yoshiserry

@yoshiserry keysenin gibi nasıl getDF? tek bir parametre mi yoksa bir dizi anahtar mı? be specific plz;)
zhangxaochen

merhaba bu, cinsiyete (erkek veya kadın) veya yıla (13, 14) karşılık gelen tek bir anahtar, sadece bir kelime. Bir anahtar dizisine sahip olabileceğinizi bilmiyordum. Bunu ne zaman ve nasıl yapacağınıza dair bir örnek paylaşır mısınız?
yoshiserry

bu soruya da bir göz atabilir misin? Cevap verebileceğini hissediyorum. Yine panda veri çerçeveleriyle ilgilidir. stackoverflow.com/questions/22086619/…
yoshiserry

1
GenderVe Yearher ikisinin de dize olması gerektiğini unutmayın , yani, 'Gender've 'Year'.
Steven C. Howell

22

Bir filtre olarak kullanmak istediğiniz ve birden fazla sütuna bağlı olan daha genel boole fonksiyonları için şunları kullanabilirsiniz:

df = df[df[['col_1','col_2']].apply(lambda x: f(*x), axis=1)]

burada f, col_1 ve col_2'den her öğe çiftine (x1, x2) uygulanan ve istediğiniz herhangi bir koşula (x1, x2) bağlı olarak True veya False döndüren bir işlevdir.



10

Birinin daha hızlı filtreleme yönteminin ne olduğunu merak etmesi durumunda (kabul edilen cevap veya @ redreamality'den gelen cevap):

import pandas as pd
import numpy as np

length = 100_000
df = pd.DataFrame()
df['Year'] = np.random.randint(1950, 2019, size=length)
df['Gender'] = np.random.choice(['Male', 'Female'], length)

%timeit df.query('Gender=="Male" & Year=="2014" ')
%timeit df[(df['Gender']=='Male') & (df['Year']==2014)]

100.000 satır için sonuçlar:

6.67 ms ± 557 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
5.54 ms ± 536 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

10.000.000 satır için sonuçlar:

326 ms ± 6.52 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
472 ms ± 25.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Yani sonuçlar boyuta ve verilere bağlıdır. Dizüstü bilgisayarımda query()500 bin satırdan sonra hızlanıyor. Dahası, dizge aramasının Year=="2014"gereksiz bir ek yükü vardır ( Year==2014daha hızlıdır).


2
Bununla birlikte, querysözdiziminin daha düzgün ve SQL'e yakın olduğunu düşünüyorum , bu da o zamandan beri veriler için güzel kılıyor. Pastadaki chery, birçok sırayla daha hızlı olması :)
csgroen

1

Sen kullanarak kendi filtre işlevi oluşturabilir queryiçinde pandas. Burada dfsonuçları tüm kwargsparametrelere göre filtreleyebilirsiniz . kwargsKendiniz için filtre işlevi elde etmek için bazı doğrulayıcılar ( filtreleme) eklemeyi unutmayın df.

def filter(df, **kwargs):
    query_list = []
    for key in kwargs.keys():
        query_list.append(f'{key}=="{kwargs[key]}"')
    query = ' & '.join(query_list)
    return df.query(query)

Zarif çözüm için teşekkürler! Bence diğerlerinin en iyisi bu. Sorguyu kullanmanın verimliliğini, onu bir işlev olarak kullanmanın çok yönlülüğüyle birleştirir.
A Merii

0

np.logical_andOperatörü değiştirmek &(veya np.logical_ordeğiştirmek için |) kullanarak birden çok sütuna (ikiden fazla) göre filtreleyebilirsiniz.

Birden çok alan için hedef değerler sağlarsanız, işi yapan örnek bir işlevi burada bulabilirsiniz. Bunu farklı filtreleme türleri ve başka şeyler için uyarlayabilirsiniz:

def filter_df(df, filter_values):
    """Filter df by matching targets for multiple columns.

    Args:
        df (pd.DataFrame): dataframe
        filter_values (None or dict): Dictionary of the form:
                `{<field>: <target_values_list>}`
            used to filter columns data.
    """
    import numpy as np
    if filter_values is None or not filter_values:
        return df
    return df[
        np.logical_and.reduce([
            df[column].isin(target_values) 
            for column, target_values in filter_values.items()
        ])
    ]

Kullanım:

df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [1, 2, 3, 4]})

filter_df(df, {
    'a': [1, 2, 3],
    'b': [1, 2, 4]
})
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.