複数の列でパンダデータフレームをフィルタリングする方法


98

データフレーム(df)を単一の列でフィルタリングするには、男性と女性のデータを考慮すると、

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

質問1-しかし、データが複数年にわたっていて、2014年の男性のみを見たい場合はどうすればよいですか?

他の言語では、私は次のようなことをするかもしれません:

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

(これを行い、新しいデータフレームオブジェクトで元のデータフレームのサブセットを取得したい場合を除く)

質問2.これをループで実行し、年と性別の一意のセットごとにデータフレームオブジェクトを作成するにはどうすればよいですか(例:2013-男性、2013-女性、2014-男性、2014-女性のdf)

for y in year:

for g in gender:

df = .....

フィルタリングしますか、それともグループ化しますか?年と性別の一意のセットごとに個別のDataFrameを作成する場合は、を参照してくださいgroupby
BrenBarn 2014

1
この回答は、パンダのブールインデックスと論理演算子の包括的な概要を示しています。
cs95

回答:


168

&演算子を使用して、サブステートメントを()次のようにラップすることを忘れないでください:

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

dictforループを使用してデータフレームを格納するには:

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

編集:

あなたのためのデモgetDF

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

print genDF(dic, 'male', 2014)

素晴らしい回答zhangxaochen-回答を編集して、データフレーム(年と性別のデータを含む)を作成するforループを実行する方法を下部に表示して、後でgetDFメソッドからアクセスできるようにデータフレームを辞書に追加できますか?def GetDF(dict、key):return dict [key]
yoshiserry

@yoshiserry keyあなたはgetDFどうですか?単一のパラメーターまたはキーのタプル?特定の
plzであること

こんにちはそれは、性別(男性または女性)または年(13、14)に対応する単一のキー(単なる単語)です。キーのタプルがあることを知りませんでした。いつどのようにこれを行うのか、例を挙げていただけますか?
yoshiserry 2014

この質問もご覧ください。答えてもらえる気がします。再びパンダのデータフレームに関連しています。 stackoverflow.com/questions/22086619/...
yoshiserry

1
なお、Gender及びYear両方の文字列、すなわち、あるべき'Gender''Year'
スティーブンC.ハウエル

22

フィルターとして使用し、複数の列に依存する、より一般的なブール関数の場合は、以下を使用できます。

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

ここで、fはcol_1とcol_2からの要素のすべてのペア(x​​1、x2)に適用され、必要な条件(x1、x2)に応じてTrueまたはFalseを返す関数です。


11

パンダ0.13から始めてください。これが最も効率的な方法です。

df.query('Gender=="Male" & Year=="2014" ')

1
なぜこれは受け入れられた答えよりも効率的であるべきですか?
Bouncner

@Bouncnerは、投票数の多い回答に対してそれを検証します。
夢想の再現

4
この答えは、ベンチマークを表示することで改善できます
nardeas

6

誰かがフィルタリングのより速い方法を何と思っているのか(受け入れられた答えまたは@redreamalityからのもの):

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行の結果:

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行の結果:

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)

したがって、結果はサイズとデータに依存します。私のラップトップでquery()は、50万行後に高速になります。さらに、での文字列検索にYear=="2014"は不要なオーバーヘッドがあります(Year==2014高速です)。


1

queryin を使用して独自のフィルター関数を作成できますpandas。ここではdf、すべてのkwargsパラメータによる結果のフィルタリングがあります。kwargs独自のフィルター関数を取得するためにいくつかのバリデーター(フィルター)を追加することを忘れないでください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)

エレガントなソリューションをありがとう!残りの中で最高だと思います。クエリを使用する効率と、クエリを関数として持つ汎用性を兼ね備えています。
Merii

0

np.logical_and演算子を使用して置換する&(またはnp.logical_orを置換する|)ことで、複数の列(3つ以上)でフィルタリングできます

複数のフィールドにターゲット値を指定した場合に、ジョブを実行する関数の例を次に示します。これをさまざまなタイプのフィルタリングに適合させることができます。

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()
        ])
    ]

使用法:

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

filter_df(df, {
    'a': [1, 2, 3],
    'b': [1, 2, 4]
})
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.