SQLのこれって、Python+Pandasだとどうやるんだっけ?(後編)

panda2 Python

panda2
前回の続き。
「SQLのこれって、Pandasでどうやるんだっけ???」を、SQLと比較しながら解説していきます。
なお、データの事前準備のやり方などは
SQLのこれって、Python+Pandasだとどうやるんだっけ?(前編)を参照してください。

 

NULLを別の値に変換する

SQLだとこんな感じにやるヤツ。

SELECT ename, nvl(comm, 0) AS nvlcomm FROM emp;

Pandasなら、こう
[code language=”python”]
print(df_emp.fillna({‘comm’: 0})[[‘ename’, ‘comm’]])
[/code]

[code language=”python” gutter=”false”]
ename nvlcomm
0 SMITH 0.0
1 ALLEN 300.0
2 WARD 500.0

・・・(省略)・・・

[/code]

ちなみに、全列をすべて同じ値で変換するならこうも書ける。
[code language=”python”]
print(df_emp.fillna(0)[[‘ename’, ‘comm’]])
[/code]

 

NULLを平均値、中央値、最頻値、前後の値に変換する

SQLではやったことないけど、Pandasならこう言う変換もできる。

平均値

平均値は「mean」を使用する。
[code language=”python”]
print(df_emp.fillna(df_emp[‘comm’].mean())[[‘ename’, ‘comm’]])
[/code]

[code language=”python” gutter=”false”]
0 SMITH 550.0
1 ALLEN 300.0
2 WARD 500.0

・・・(省略)・・・

[/code]

中央値

中央値は「median」を使用する。
[code language=”python”]
print(df_emp.fillna(df_emp[‘comm’].median())[[‘ename’, ‘comm’]])
[/code]

[code language=”python” gutter=”false”]
0 SMITH 400.0
1 ALLEN 300.0
2 WARD 500.0

・・・(省略)・・・

[/code]

最頻値

最頻値は「mode」を使用する。なお、「mode」はDataFrameを返却するので、
「iloc」で先頭の値を取得している。
[code language=”python”]
print(df_emp.fillna(df_emp[‘comm’].mode().iloc[0])[[‘ename’, ‘comm’]])
[/code]

[code language=”python” gutter=”false”]
0 SMITH 0.0
1 ALLEN 300.0
2 WARD 500.0

・・・(省略)・・・

[/code]

前後の値

前の値はfillnaのオプションで「method=’ffill’」を指定する。
同様に後の値は「method=’bfill’」を指定する。
時系列のデータ分析などの時に利用すると便利かも。
[code language=”python”]
print(df_emp.fillna(method=’ffill’)[[‘ename’, ‘comm’]])
[/code]

[code language=”python” gutter=”false”]
ename comm
0 SMITH NaN
1 ALLEN 300.0
2 WARD 500.0

・・・(省略)・・・

[/code]

 

表を並び替える

SQLならよくやるやつ。

SELECT ename, sal, comm FROM emp
ORDER BY sal DESC, comm DESC;

これを自前で作るとなかなか面倒だけど、Pandasなら楽勝。
[code language=”python”]
print(df_emp.sort_values(by=["sal", "comm"], ascending=[False,False])[[‘ename’, ‘sal’, ‘comm’]])
[/code]

[code language=”python” gutter=”false”]
ename sal comm
8 KING 5000 NaN
7 SCOTT 3000 NaN
12 FORD 3000 NaN

・・・(省略)・・・

[/code]

 

二つの表を結合する

これもSQLなら簡単だけど、自前で作るとかなり面倒。

SELECT emp.ename, dept.dname
FROM emp, dept
WHERE emp.deptno = dept.deptno;

Pandasではいくつか方法があるけれど、今回は汎用的な「merge」を使用する。
[code language=”python”]
print(pd.merge(df_emp, df_dept, how=’inner’, on=’deptno’)[[‘ename’, ‘dname’]])
[/code]

[code language=”python” gutter=”false”]
ename dname
0 SMITH RESEARCH
1 JONES RESEARCH
2 SCOTT RESEARCH

・・・(省略)・・・

[/code]

 

表を自己結合する

自分自身と結合するやつ。
emp表は上司のempnoがあるので、emp表同士を結合して上司のenameを表示する。

SELECT worker.ename, worker.mgr, manager.ename
FROM emp worker INNER JOIN emp manager
ON worker.mgr = manager.empno;

Pandasならこう。
[code language=”python”]
print(pd.merge(df_emp, df_emp, how=’inner’, left_on=’mgr’, right_on=’empno’)[[‘ename_x’, ‘mgr_x’, ‘ename_y’]])
[/code]

[code language=”python” gutter=”false”]
ename_x mgr_x ename_y
0 SMITH 7902.0 FORD
1 ALLEN 7698.0 BLAKE
2 WARD 7698.0 BLAKE

・・・(省略)・・・

[/code]

 

表を外部結合する

結合する対象が存在しないデータも表示する場合。
dept表の「OPERATIONS」は所属する従業員がいない
(emp表にdeptnoが40のデータが存在しない)ので、
単純に結合すると表示されない。
SQLならLEFT JOINするところ。

SELECT e.ename, d.dname
FROM dept d LEFT JOIN emp e
ON e.deptno = d.deptno;

Pandasも基本は一緒。結合方法「how=’left’」を指定する。
[code language=”python”]
print(pd.merge(df_dept, df_emp, how=’left’, on=’deptno’)[[‘ename’, ‘dname’]])
[/code]

[code language=”python” gutter=”false”]
ename dname
0 CLARK ACCOUNTING
1 KING ACCOUNTING

・・・(省略)・・・

14 NaN OPERATIONS
[/code]

 

表の件数を取得する

SELECT COUNT(*) FROM emp;

Pandasならこう。
[code language=”python”]
print(len(df_emp))
[/code]

ちなみに、列を指定するとNULLを除外してくれる。
[code language=”python”]
print(df_emp[‘comm’].count())
[/code]

 

列の合計を取得する

SELECT SUM(comm) FROM emp;

Pandasならこう。
[code language=”python”]
print(df_emp[‘comm’].sum())
[/code]

[code language=”python” gutter=”false”]
2200.0
[/code]

 

列の平均を取得する

SELECT AVG(comm) FROM emp;

Pandasならこう。
[code language=”python”]
print(df_emp[‘comm’].mean())
[/code]

[code language=”python” gutter=”false”]
550.0
[/code]

 

列の値ごとに集計し、件数を取得する

SQLなら「GROUP BY」句を使用するヤツ。

SELECT job, COUNT(*) FROM emp GROUP BY JOB;

Pandasも基本はいっしょ。
[code language=”python”]
print(df_emp.groupby(‘job’)[‘job’].count())
[/code]

[code language=”python” gutter=”false”]
job
ANALYST 2
CLERK 4
MANAGER 3

・・・(省略)・・・

[/code]

 

列の値ごとに集計し、合計を取得する

SELECT job, SUM(sal) FROM emp GROUP BY JOB;

Pandasならこう。
[code language=”python”]
print(df_emp.groupby(‘job’)[‘sal’].sum())
[/code]

[code language=”python” gutter=”false”]
job
ANALYST 6000
CLERK 4150
MANAGER 8275

・・・(省略)・・・

[/code]

 

集計した結果を条件に抽出する

SQLならHAVINGを使うケース。

SELECT deptno, AVG(sal) FROM emp
GROUP BY deptno HAVING AVG(sal) >= 2000;

Pandasならこう。reset_indexで列名を再設定しないと「query」が使えないので注意。
[code language=”python”]
print(df_emp.groupby(‘deptno’)[‘sal’].mean().reset_index().query(‘sal >= 2000’))
[/code]

[code language=”python” gutter=”false”]
deptno sal
0 10 2916.666667
1 20 2175.000000
[/code]

 

検索結果を条件にして、さらに絞り込む(副問い合わせ)

SQLなら副問い合わせで絞り込むケース。

SELECT ename FROM emp WHERE empno IN
( SELECT mgr FROM emp WHERE job = 'CLERK' );

Pandasならこう。
[code language=”python”]
print(df_emp[df_emp[‘empno’].isin(df_emp[df_emp[‘job’] == ‘CLERK’][‘mgr’])][‘ename’])
[/code]

[code language=”python” gutter=”false”]
5 BLAKE
6 CLARK
7 SCOTT

・・・(省略)・・・

[/code]

今回はここまで。
もっと色々できると思うけど、その辺りはおいおい。

コメント

タイトルとURLをコピーしました