モブプロな人たちのブログ

Web サービス開発しているエンジニアの日記です。Python 大好き Flask 大好き。たまに Swift で iOS ゲーム開発も。

Pandas で JOIN して複数カラムを乗算する話

こんにちは、kaorr です。

一人アドベントカレンダー3日目です。

はじめに

SQL 使えない場面で Python で頑張るシリーズです。

今回は、標準ライブラリではなく、Pandas を使う話です。

f:id:kaorr_mob:20171203110732j:plain

Pandas 可愛いよ Pandas。

前提

  • データ(テーブル)は2つ。

  • 社員ごとのベース給与額とベース賞与額を格納。一意な値として、社員 ID を持つ。

  • 社員ごとの評価によるレートを格納。一意な値として、社員 ID を持つ。

  • まず、上記の2つのテーブルを結合して、社員ごとの給与等と評価レートを1つのテーブルにする。

  • 次に、ベース給与額とベース賞与額にレートを乗算して、最終的な金額を出力したい。

コード全体

こんな感じになります。

import pandas as pd

# 社員ごとのベース給与額とベース賞与額
df_emp = pd.DataFrame(
    {
        'id': [1, 2, 3],
        'name': ['Tanaka', 'Yamada', 'Yoshida'],
        'salary': [200.0, 200.0, 1000.0],
        'bonus': [400.0, 400.0, 2500.0]
    }
)

# 社員ごとの評価によるレート
df_rate = pd.DataFrame(
    {
        'emp_id': [1, 2, 3],
        'rate': [1.2, 1.5, 0.7]
    }
)

# df_emp['id'] と df_rate['emp_id'] で INNER JOIN する
df = pd.merge(df_emp, df_rate, left_on='id', right_on='emp_id', how='inner')

# レート適用前のデータ
print(df[['name', 'salary', 'bonus', 'rate']])

#       name  salary   bonus  rate
# 0   Tanaka   200.0   400.0   1.2
# 1   Yamada   200.0   400.0   1.5
# 2  Yoshida  1000.0  2500.0   0.7

# レート適用処理
for column in ['salary', 'bonus']:
    df[column] *= df['rate']

# レート適用後のデータ
print(df[['name', 'salary', 'bonus']])

#       name  salary   bonus
# 0   Tanaka   240.0   480.0
# 1   Yamada   300.0   600.0
# 2  Yoshida   700.0  1750.0

おわりに

今回は merge を使いましたが、DataFrame の join を使ってもできそうな気がします。(ちょっと試した感じだと分かり難かったですが。)

レート適用は、for 文でグルグル回して処理しましたが、apply を使うともうちょっとスッキリしそうです。例えば、

df[['salary', 'bonus']].apply(lambda x: x * df['rate'])

という感じのコードにしても、前述のコードと同じ結果が得られます。

とはいえ、こっちのコードはちょっと直感的じゃない(あくまで個人的には)ので、うーんという感じですね・・・。

f:id:kaorr_mob:20171203110427j:plain

Pandas は奥が深い。