LoginSignup
110
140

More than 1 year has passed since last update.

逆引き DataFrameのデータ抽出(選択)処理

Last updated at Posted at 2019-03-23

DataFrameのデータ抽出処理のまとめ。こういうのでいいんだよ的なものなので、細かい内容は他の方の記事を参考にしてください。データ入出力処理はこちら

逆引き用の分類

何(インデックスor列名or値)を対象にどうやって(抽出条件)データを抽出したいのかにマッチする方法が何かを整理しています。おすすめの選択方法をリンク付きにしました。

抽出条件 インデックス(ラベル) 列名 dfの値
= 値
isin 複数の値
df.loc
df.reindex
df.filter
df.query
df[bools]
df[]
df.loc
df.reindex
df.filter
(df.T.query.T)
df[bools]
df.query
df[bools]
!= 値
not isin 複数の値
df.drop
df.query
df[bools]
df.drop
(df.T.query.T)
df[bools]
df.query
df[bools]
スライス df.loc
<,≤,>,≥ 値 df.query
df[bools]
(df.T.query.T)
df[bools]
df.query
df[bools]
like 値 df.filter
df.query
df[bools]
df.filter
(df.T.query.T)
df[bools]
df.query
df[bools]
正規表現 df.filter
df.query
df[bools]
df.filter
(df.T.query.T)
df[bools]
df.query
df[bools]
関数 df.query
df[bools]
(df.T.query.T)
df[bools]
df.query
df[bools]
上記組み合わせ(and,or,not) df.query
df[bools]
(df.T.query.T)
df[bools]
df.query
df[bools]

正規表現については以下を参照。
https://qiita.com/luohao0404/items/7135b2b96f9b0b196bf3

以下のデータを対象に、次のセクション以降で具体的なデータ抽出方法を説明します。

df = pd.DataFrame({'都道府県':['千葉県','三重県','北海道','神奈川県'],
                   'まいわし':[10,20,100,np.nan],
                   'かたくちいわし':[20,30,60,60],
                   'あじ':[np.nan,np.nan,100,30]}
                 ).set_index('都道府県')
都道府県 まいわし かたくちいわし あじ
千葉県 10 20 NaN
三重県 20.0 30 NaN
北海道 100.0 60 100.0
神奈川県 NaN 60 30.0

注)上の表の数字に意味はありません。神奈川でまいわしが獲れない訳でも、千葉・三重であじが獲れない訳でもありません。気分を悪くされた方がいたら申し訳ありません。私は神奈川のいわしも、千葉、三重のあじもおいしいと思っています。

DataFrame[]

https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#slicing-ranges
https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#attribute-access

列名 == 値、列名 isin 複数の値

df['まいわし'] # Seriesになる
# 都道府県
# 千葉県      10.0
# 三重県      20.0
# 北海道     100.0
# 神奈川県      NaN
# Name: まいわし, dtype: float64

df[['まいわし']] # DataFrameになる
# 都道府県 まいわし
# 千葉県    10.0 
# 三重県    20.0 
# 北海道    100.0
# 神奈川県   NaN 

df[['まいわし','かたくちいわし']]
# 都道府県 まいわし かたくちいわし
# 千葉県    10.0    20
# 三重県    20.0    30
# 北海道    100.0   60
# 神奈川県   NaN    60

DataFrame.loc

インデックス == 値 、インデックス isin 複数の値

df.loc['千葉県'] #Seriesになる
# まいわし      10.0
# かたくちいわし 20.0
# あじ           NaN
# Name: 千葉県, dtype: float64

df.loc[['千葉県']] #DataFrameになる
# 都道府県 まいわし かたくちいわし あじ
#  千葉県    10.0        20      NaN

df.loc[['三重県','神奈川県'],:]
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

列名 == 値、 列名 isin 複数の値

df.loc[:,'まいわし'] # Seriesになる
# 都道府県
# 千葉県      10.0
# 三重県      20.0
# 北海道     100.0
# 神奈川県      NaN
# Name: まいわし, dtype: float64

df.loc[:,['まいわし']] # DataFrameになる
# 都道府県 まいわし
# 千葉県    10.0 
# 三重県    20.0 
# 北海道    100.0
# 神奈川県   NaN 

df.loc[:,['まいわし','かたくちいわし']]
# 都道府県 まいわし かたくちいわし
# 千葉県    10.0    20
# 三重県    20.0    30
# 北海道    100.0   60
# 神奈川県   NaN    60

DataFrame.reindex

インデックス isin 複数の値

df.reindex(index=['三重県','神奈川県'])
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

列名 isin 複数の値

df.reindex(columns=['まいわし','かたくちいわし'])
# 都道府県 まいわし かたくちいわし
# 千葉県    10.0    20
# 三重県    20.0    30
# 北海道    100.0   60
# 神奈川県   NaN    60

DataFrame.drop

インデックス not isin 複数の値

df.drop(index=['千葉県','北海道'])
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

列名 not isin 複数の値

df.drop(columns=['あじ'])
# 都道府県 まいわし かたくちいわし
# 千葉県    10.0    20
# 三重県    20.0    30
# 北海道    100.0   60
# 神奈川県   NaN    60

DataFrame.filter

インデックス isin 複数の値

df.filter(items=['三重県','神奈川県'],axis=0) # df.loc[['三重県','神奈川県']]と同じ
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

列名 isin 複数の値

df.filter(items=['まいわし','かたくちいわし']) # df[['まいわし','かたくちいわし']]と同じ
# 都道府県 まいわし かたくちいわし
# 千葉県    10.0    20
# 三重県    20.0    30
# 北海道    100.0   60
# 神奈川県   NaN    60

インデックス like 値

df.filter(like='県',axis=0)
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

列名 like 値

df.filter(like='いわし',axis=1)
# 都道府県 まいわし かたくちいわし
# 千葉県    10.0    20
# 三重県    20.0    30
# 北海道    100.0   60
# 神奈川県   NaN    60

正規表現 search インデックス

df.filter(regex='^..県',axis=0)
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN

正規表現 search 列名

df.filter(regex='.*いわ',axis=1)
# 都道府県 まいわし かたくちいわし
# 千葉県    10.0    20
# 三重県    20.0    30
# 北海道    100.0   60
# 神奈川県   NaN    60

DataFrame.query

インデックス(or dfの値) == 値、インデックス(or dfの値) isin 複数の値

df.query('都道府県=="千葉県"') # df.query('index=="千葉県")でもOK
# 都道府県 まいわし かたくちいわし あじ
#  千葉県    10.0        20      NaN

df.query('都道府県 in ["三重県","神奈川県"]') #df.query('都道府県==[...])でもOK
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

# NaNの場合は注意
df.query('まいわし.isna()', engine='python') #df.query('まいわし!=まいわし')でもOK(分かりにくいけど) 
# 都道府県 まいわし かたくちいわし あじ
# 神奈川県    NaN         60     30.0

インデックス(or dfの値) != 値、インデックス(or dfの値) not isin 複数の値

hokkaido = '北海道'
df.query('都道府県!=@hokkaido') #@で変数使用可
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

chi_hok = ['千葉県','北海道']
df.query('都道府県 not in @chi_hok')
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

# NaNの場合は注意
df.query('まいわし.notna()', engine='python') #df.query('まいわし==まいわし')でもOK(分かりにくいけど) 
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN
# 北海道    100.0        60     100.0 

インデックス(or dfの値) <,≤,>,≥ 値

df.query('まいわし>0')
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN
# 北海道    100.0        60     100.0 

インデックス(or dfの値) like 値

df.query('index.str.contains("道")', engine='python')
# 都道府県 まいわし かたくちいわし あじ
# 北海道    100.0        60     100.0

正規表現 match インデックス(or dfの値)

df.query('index.str.match("^..県")', engine='python')
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN

関数(インデックス(or dfの値))

上の例で@を付けて変数を渡しましたが、関数を渡せば任意の関数を使って抽出できます。

def is_thirty(x):
    if type(x)==str:
        return x.find('三重')>-1
    elif str(x).isdigit():
        return x==30
    else:
        return False

df.query('index.apply(@is_thirty)', engine='python')
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN

df.query('かたくちいわし.apply(@is_thirty)', engine='python')
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN

インデックス(or dfの値) の条件組み合わせ

df.query('まいわし>0 and あじ > 0')
# 都道府県 まいわし かたくちいわし あじ
# 北海道    100.0        60     100.0 

df.query('not まいわし>0')
# 都道府県 まいわし かたくちいわし あじ
# 神奈川県    NaN         60     30.0

DataFrame[bools]

DataFrame[bools]は私の勝手な表現です。df[]やdf.loc[]にboolのリストを渡すと、Trueのものだけが抽出されるので、そのように書いています。詳しくは以下を参照してください。
Python pandas データ選択処理をちょっと詳しく <中編>

インデックス == 値

df[df.index=='千葉県'] # df.loc[df.index=='千葉県']でもOK
# 都道府県 まいわし かたくちいわし あじ
#  千葉県    10.0        20      NaN

インデックス isin 複数の値

df[df.index.isin(['三重県','神奈川県'])] #df.loc[df.index.isin(['三重県','神奈川県'])]でもOK
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

列名 == 値

df.loc[:,df.columns=='あじ'] #df[['あじ']]と同じ
# 都道府県 あじ
#  千葉県  NaN
#  三重県  NaN
#  北海道  100.0
#  神奈川県 30.0

列名 isin 複数の値

df.loc[:,df.columns.isin(['まいわし','かたくちいわし'])] #df[['まいわし','かたくちいわし']]と同じ
# 都道府県 まいわし かたくちいわし
# 千葉県    10.0    20
# 三重県    20.0    30
# 北海道    100.0   60
# 神奈川県   NaN    60

dfの値 == 値

df[df['あじ']==30] # df.loc[df['あじ']==30]でもOK
# 都道府県 まいわし かたくちいわし あじ
#  神奈川県   NaN       60       30.0

dfの値 isin 複数の値

df[df['かたくちいわし'].isin([20,30])] # df.loc[df['かたくちいわし'].isin([20,30])]でもOK
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN

インデックス != 値

df[df.index !='北海道'] # []内は、~(df.index='北海道')でもnp.logical_not(df.index='北海道')でもOK。というかdropを使おう。
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

インデックス not isin 複数の値

df[~(df.index.isin(['千葉県','北海道']))] # dropを使おう。
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN
# 神奈川県    NaN         60     30.0

列名 != 値

df.loc[:,df.columns !='あじ'] # []内は、~(df.clumns='あじ')でもnp.logical_not(df.index='あじ')でもOK。というかdropを使おう。
# 都道府県 まいわし かたくちいわし
# 千葉県    10.0    20
# 三重県    20.0    30
# 北海道    100.0   60
# 神奈川県   NaN    60

列名 not isin 複数の値

df.loc[:,~(df.columns.isin(['まいわし','かたくちいわし']))] # dropを使おう
# 都道府県 あじ
#  千葉県  NaN
#  三重県  NaN
#  北海道  100.0
#  神奈川県 30.0

dfの値 != 値

df[df['あじ'] != 30]
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN
# 北海道    100.0        60     100.0

dfの値 not isin 複数の値

df[~(df['あじ'].isin([30,100]))]
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN

インデックス(or 列名、dfの値) <,≤,>,≥ 値

df[df['まいわし']>0] #dfの値の場合。インデックスの場合はdf.index、列名の場合はdf.columnで条件判定。
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN
# 北海道    100.0        60     100.0 

インデックス(or 列名、dfの値) like 値

df[df.index.str.contains('道')] #インデックスの場合。列名の場合はdf.column、dfの値の場合はdf[列名]に.str.containsをつなげる。
# 都道府県 まいわし かたくちいわし あじ
# 北海道    100.0        60     100.0

正規表現 match インデックス(or 列名、dfの値)

df[df.index.str.match('^..県')] #インデックスの場合。列名の場合はdf.column、dfの値の場合はdf[列名]に.str.matchをつなげる。
# 都道府県 まいわし かたくちいわし あじ
# 千葉県     10.0        20      NaN
# 三重県     20.0        30      NaN

関数(インデックス(or 列名、dfの値) )

def is_thirty(x):
    if type(x)==str:
        return x.find('三重')>-1
    elif str(x).isdigit():
        return x==30
    else:
        return False

df[df.index.map(is_thirty)] # applyは使えない
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN

df[df['かたくちいわし'].apply(is_thirty)]
# 都道府県 まいわし かたくちいわし あじ
# 三重県     20.0        30      NaN

インデックス(or 列名、dfの値) の条件組み合わせ

df[(df['まいわし']>0) & (df['あじ']>0)] # df.query('まいわし>0 and あじ > 0')と同じ
# 都道府県 まいわし かたくちいわし あじ
# 北海道    100.0        60     100.0 

df[~(df['まいわし']>0)]
# 都道府県 まいわし かたくちいわし あじ
# 神奈川県    NaN         60     30.0

df.loc[df['まいわし']>0,df.columns.str.contains('いわし')] #インデックスとdfの値のboolsは&や|でつなげても良いが、列名のboolsとその他はつなげられない。locの別の引数として設定する。
# 都道府県  まいわし かたくちいわし
#  千葉県    10.0       20
#  三重県    20.0       30
#  北海道   100.0       60

DataFrame.xs

参考

110
140
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
110
140