やりたいこと
-
dataframe
から複数条件で行を抽出したい - データには欠損値が含まれる
試してみたこと
データ抽出にはいくつか方法があるようだけれど今回は下記の2つで試した
-
pandas
のquery
関数を使用する -
query
を使わないで列名を使用する
サンプルデータ
ID | NAME | ADDRESS_1 | ADDRESS_2 | CORPORATIONNUMBER | COUNTRY |
---|---|---|---|---|---|
12345 | まるばつ産業 | 東京都中央区 | 東京都千代田区 | 25671900 | JAPAN |
26890 | どれみ物産 | NaN | 東京都港区 | 10008765 | JAPAN |
66635 | abc corporation | NaN | NaN | 57682399 | USA |
抽出条件
- COUNTRYがJAPANであること
- ADDRESS_1があり、かつADDRESS_2もあること
抽出したい行
ID | NAME | ADDRESS_1 | ADDRESS_2 | CORPORATIONNUMBER | COUNTRY |
---|---|---|---|---|---|
12345 | まるばつ産業 | 東京都中央区 | 東京都千代田区 | 25671900 | JAPAN |
出力したいカラム
COUNTRY以外を出力する
| ID | NAME| ADDRESS_1| ADDRESS_2| CORPORATIONNUMBER|
|:-:|:-:|:-:|:-:|:-:|:-:|
| 12345 |まるばつ産業 | 東京都中央区 | 東京都千代田区 | 25671900 |
条件式をつくる
- COUNTRYがJAPANであること
query
COUNTRY=='JAPAN'
queryを使わない
df[COUNTRY]=='JAPAN'
- ADDRESS_1があり、かつADDRESS_2もあること
= ADDRESS_1が欠損値(NaN)ではなく、ADDRESS_2も欠損値でない
query
# and でつなぐ
ADDRESS_1.notna() and ADDRESS_2.notna()
# & でもよい
ADDRESS_1.notna() & ADDRESS_2.notna()
queryを使わない
# & を使う
df[ADDRESS_1].notna() & df[ADDRESS_2].notna()
ちなみに「または」の条件の時はこうなる
query
# or でつなぐ
ADDRESS_1.notna() or ADDRESS_2.notna()
# | でもよい
ADDRESS_1.notna() | ADDRESS_2.notna()
queryを使わない
# | を使う
df[ADDRESS_1].notna() | df[ADDRESS_2].notna()
-
query
ではand
やor
が使えるが、query
を使わない場合は使えないので注意
条件式を組み立てる
query
# 条件を&でつないでダブルクォーテーションでくるむ
df.query("COUNTRY =='JAPAN' & ADDRESS_1.notna() & ADDRESS_2.notna()")
queryを使わない
# 条件を&でつないでダブルクォーテーションでくるむ
df.query("df[COUNTRY] =='JAPAN' & df[ADDRESS_1].notna() & df[ADDRESS_2].notna()")
抽出したい列を選択する
-
loc
を使う -
loc
[対象行:,(列名)]
列選択
# 全ての行を対象として'ID','NAME','ADDRESS_1','ADDRESS_2','CORPORATIONNUMBER'列を抽出する場合
loc[:,('ID','NAME','ADDRESS_1','ADDRESS_2','CORPORATIONNUMBER')]
# IDが12345の行を対象として'ID','NAME','ADDRESS_1','ADDRESS_2','CORPORATIONNUMBER'列を抽出する場合
loc['12345' :,('ID','NAME','ADDRESS_1','ADDRESS_2','CORPORATIONNUMBER')]
サンプルコード
test
import pandas as pd
import codecs
# 読み込むcsv
target = 'sample.csv'
# 出力先
out = 'output.tsv'
with codecs.open(target, mode='r', encoding='shift-jis', errors='ignore') as f:
df = pd.read_csv(
f,
sep=',',
engine='python', # encodingのかわりにengine='python'にするとおまかせになるらしい
# 特定のカラムだけ出力したい時は```usecols```で設定する
usecols=[
'ID',
'NAME',
'ADDRESS_1',
'ADDRESS_2',
'CORPORATIONNUMBER',
'COUNTRY'
],
# 一見数値に見えるカラムの値も文字として扱いたいので文字列にコンバートしておく
# 何もしないと出力時に小数点以下がついたりするので注意
converters={
'ID': str,
'CORPORATIONNUMBER': str,
}
)
# データ抽出, 列選択
result = df.query("COUNTRY =='JAPAN' & ADDRESS_1.notna() & ADDRESS_2.notna()").loc[:,('ID','NAME','ADDRESS_1','ADDRESS_2','CORPORATIONNUMBER')]
# または
result = df.query("df[COUNTRY] =='JAPAN' & df[ADDRESS_1].notna() & df[ADDRESS_2].notna()").loc[:,('ID','NAME','ADDRESS_1','ADDRESS_2','CORPORATIONNUMBER')]
# 出力
result.to_csv(out, sep='\t',encoding='utf-8',index=False)