普段SQLを喋る人がPythonの海を泳いだとき、Pandasの喋り方、、さらにはPolarsの喋り方が分からなくなり、、対応表を作りました。
その1です。
もくじ
使うデータ
日付時刻が入っていて、たまに空欄がある、、、
実業務ではよくあるうんこデータです
読み込み
Pandas/Polarsのみ記述
1 2 3 4 5 6 7 | #----- Pandas (pd) df_pd = pd.read_csv('./sample_data.csv') #----- Polars (pl) df_pl = pl.read_csv('./sample_data.csv') #----- Polarsその2:Pandas.DataFrameから変換(pyarrowモジュールが必要) df_pl2 = pl.from_pandas(df_pd) ## 逆の処理=df_pl2.to_pandas()は日本語をファイル出力するときよく使う |
SELECT
列の選択
1 | select DAY, YEN from TBL |
↓Python
1 2 3 4 5 6 7 8 | # -----Pandasその1:列の名前だけ df_pd[['DAY', 'YEN']] # -----Pandasその2:すべての行の、特定の列 df_pd.loc[:, ['DAY', 'YEN']] # -----Polars df_pl[['DAY', 'YEN']] # -----Polarsその2: df_pl.select(['DAY', 'YEN']) |
WHERE
完全一致
1 | select * from TBL where SHOP='ローソン' |
↓
1 2 3 4 5 6 7 | # -----Pandas df_pd[df_pd['SHOP']=='ローソン'] ## []の中に、条件を記述します。 ## もっというと、df_pd['SHOP']=='ローソン'はTrue/FalseのSeries(1次元配列)を返しています # -----Polars df_pl.filter(pl.col('SHOP')=='ローソン') ## pl.col('列名')を使って、条件を記述します。データフレーム名を意識しなくていいので楽 |
IN句
1 | select * from TBL where SHOP in ('ローソン', 'ファミマ') |
↓
1 2 3 4 5 6 | # -----Pandas df_pd[ df_pd['SHOP'].isin(['ローソン', 'ファミマ']) ] ## isin(list)で、IN句を再現できます # -----Polars df_pl.filter( pl.col('SHOP').is_in(['ローソン', 'ファミマ']) ) ## Polarsではis_in(list)と、アンダーバーが入ります |
IS NULL
1 | select * from TBL where YEN is null |
↓
1 2 3 4 5 6 | # -----Pandas df_pd[ pd.isna(df_pd['YEN']) ] ## pd.isna()でNull判定できます。厳密にはNullとNaNは意味が違いますが・・ # -----Polars df_pl.filter( pl.col('YEN').is_null() ) ## 末尾にis_null()でできます |
LIKE(部分一致)
1 | select * from TBL where SHOP like '%弁当%' |
↓
1 2 3 4 5 6 | # -----Pandas df_pd[ df_pd['SHOP'].str.contains('弁当') ] ## 前方一致はstartswith()、後方一致はendswith()です # -----Polars df_pl.filter( pl.col('SHOP').str.contains('弁当') ) ## 前方一致はstarts_with()、後方一致はends_with()です。アンダーバーが入る |
複数条件
1 2 | select * from TBL where (SHOP='ローソン' or SHOP='ファミマ') and YEN>=200 -- あえてINを使ってません・・ |
↓
1 2 3 4 5 6 7 | # ------Pandas df_pd[((df_pd['SHOP']=='ローソン') | (df_pd['SHOP']=='ファミマ')) & (df_pd['YEN']>=200)] ## []の中の条件を、((条件) | (条件)) & (条件)とします ## いちいち()を付けないと、エラーが起きやすい気がします # -----Polars df_pl.filter(((pl.col('SHOP')=='ローソン') | (pl.col('SHOP')=='ファミマ')) & (pl.col('YEN')>=200)) ## pl.colで同様に記述します |
DISTINCT
1 | select distinct * from TBL |
↓
1 2 3 4 | # -----Pandas df_pd.drop_duplicates() # -----Polars df_pl.unique() |
ORDER BY
1 | select * from TBL order by YEN |
↓
1 2 3 4 | # -----Pandas df_pd.sort_values('YEN') # -----Polars df_pl.sort('YEN') |
新しい列の作成
定数列の作成
1 | select *, 1 as ONE from TBL |
↓
1 2 3 4 5 6 7 8 9 10 | # -----Pandas df_pd['ONE'] = 1 ## 直接作成されます # -----Pandasその2:個人的にはあまり使いません df_pd = \ df_pd.assign(ONE=1) # -----Polars df_pl = \ df_pl.with_columns(pl.lit(1).alias('ONE')) ## with_columnsで、新しい列を作成します。pl.lit()で定数の列を作ります。.alias()で列の名前を付けます。 |
計算結果の格納
1 | select *, YEN*2 as DOUBLED from TBL |
↓
1 2 3 4 5 6 7 | # -----Pandas df_pd['DOUBLED'] = df_pd['YEN']*2 ## 直接作成されます # -----Polras df_pl =\ df_pl.with_columns((pl.col('YEN')*2).alias('DOUBLED')) ## pl.col()で.aliasを付けない場合、そのままpl.col()の列に格納されます |
関数
COALESCE
1 2 | select *, coalesce(YEN, 0) as YEN_ZERO from TBL; select *, coalesce(YEN, ONE) as YEN_ONE from TBL |
↓
1 2 3 4 5 6 7 8 9 | # -----Pandas df_pd['YEN_ZERO'] = df_pd['YEN'].fillna(0) df_pd['YEN_ONE'] = df_pd['YEN'].fillna(df_pd['ONE']) # -----Polars df_pl = \ df_pl.with_columns( pl.col('YEN').fill_null(0).alias('YEN_ZERO') ) df_pl = \ df_pl.with_columns( pl.col('YEN').fill_null(pl.col('ONE')).alias('YEN_ONE') ) ## 正直ちょっと面倒・・ |
CONCAT
1 | select METHOD || '_' || TYPE as TYPE2 from TBL |
↓
1 2 3 4 5 6 7 | # -----Pandas df_pd['TYPE2'] = df_pd['METHOD'] + '_' + df_pd['TYPE'] ## どれかにNullがあるとNullになるため、fillna('')を推奨 # -----Polars df_pl = \ df_pl.with_columns((pl.col('METHOD') + '_' + pl.col('TYPE')).alias('TYPE2')) ## NullがあるとNullになるため、fill_null('')推奨 |
CASE
1 | select *, case when YEN>1000 then '要注意' else '' end as FLG from TBL |
↓
1 2 3 4 5 6 7 8 | # -----Pandas df_pd['FLG'] = '' # 先にelseの値で埋める df_pd['FLG'] = df_pd['FLG'].mask(df_pd['YEN']>1000, '要注意') # 条件に一致したもののみ「要注意」で埋める ## Pandas.DataFrame.whereもあるが、maskの方が直感的なため・・・ # -----Polars df_pl = \ df_pl.with_columns( pl.when(pl.col('YEN')>1000).then(pl.lit('要注意')).otherwise(pl.lit('')).alias('FLG') ) ## pl.when(条件).then(Trueの処理).otherwise(Falseの処理)という処理ができる。それをwith_columnsやselectで包み込む |
CASE(複数カラムを使った条件式)
上記を応用すれば、複数の列を使った条件を作成可能。
ただし、whenが複数になるとき、Pandasだと順序に注意が必要(一番広いものから書いていく必要)
1 2 | select case when YEN>1000 and TYPE<>'交際費' then '要注意' else '' end as FLG2 from TBL -- 対象列の表示だけ |
↓
1 2 3 4 5 6 7 8 | # -----Pandas df_pd['FLG2'] = '' df_pd['FLG2'].mask( ((df_pd['YEN']>1000) & (df_pd['TYPE']!='交際費')), '要注意' ) ## df_pd['FLG2']に対して.maskしているが、df_pd['YEN']とdf_pd['TYPE']は各々存在するため、これで可能 # -----Polars df_pl.select( pl.when( (pl.col('YEN')>1000) & (pl.col('TYPE')!='交際費') ).then('要注意').otherwise('').alias('FLG2') ) ## pl.when(条件).then(Trueの場合).otherwise(Falseの場合)の、条件を複雑にしただけ ## こちらの方がSQLに近い |
その2では、集計関数やJOINについて書く・・・よてい。。