クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

2つの表を結合する

このレッスンのあとで: 共通の列で2つの表を結合し、結合が狙いどおりだったか確かめられる。

60分のレッスンコマンド7件JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

祝日は、お客さんが少ないのでしょうか

自転車店には、貸出の表と、別に祝日の一覧があります。店長は「祝日は暇ですか」と聞きます。

どちらの表も、1つだけでは答えられません。貸出の表には祝日の列がなく、祝日の一覧には貸出がないからです。2つに共通する日付で、つなぐ必要があります。

このレッスンのゴール

メモ

共通の列で2つの表を結合し、結合が狙いどおりだったか確かめられる。

キーワード

ことばいみれい
結合列の値が同じ行どうしを、横に並べてつなぐことmerge
キー2つの表が共通に持つ列で、相手の行を探す手がかりdate
左結合最初の表の行をすべて残す。相手がいなくても残す
内部結合両方の表に相手がいる行だけを残す
相手なしもう一方の表に見つからなかった行
一意列の中に1回しか現れないこと

学生が入力するセルは、このプレビューでは空白です。

2つの表と、共通の列

データは、小さな表に分けて持つことがよくあります。1つの事実を、1回だけ書くためです。祝日の一覧は1回だけ書き、365行にコピーはしません。

両方を使うときは、表を結合します。2つの表が持つ列を選びます。それがキーです。片方の各行が、もう片方からキーの値が同じ行を探します。

2つ目の表を作る

レッスンバーのスタートを押し、ラボが動くまで待ちます。端末に Python はありません。Run は、docker exec jupyter でラボの中のコマンドを動かします。

ラボにあるのは hires.csv だけです。最初の Run が、2025年の祝日8日を入れた2つ目のファイル holidays.csv を書きます。

祝日の一覧を書く

コマンド
docker exec jupyter sh -c "printf '%s\n' 'date,holiday' '2025-01-01,元日' '2025-01-13,成人の日' '2025-02-11,建国記念の日' '2025-03-20,春分の日' '2025-04-29,昭和の日' '2025-05-05,こどもの日' '2025-07-21,海の日' '2025-11-03,文化の日' > holidays.csv"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

読み返す

コマンド
docker exec jupyter cat holidays.csv

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

左結合は、すべての行を残す

左結合は、最初の表から始めます。その行はすべて残ります。相手が見つかれば、新しい列が埋まります。見つからなければ、空のままです。

表に情報を足すときの、安全な選び方です。列を足しても、1日も失いません。

例: 3日分を結合した結果

datehiresholiday
2025-03-19129(空)
2025-03-20125春分の日
2025-03-21141(空)

学生が入力するセルは、このプレビューでは空白です。

結合して、祝日を表示する

コマンド
docker exec jupyter python3 -c "import pandas as pd; h=pd.read_csv('hires.csv'); b=pd.read_csv('holidays.csv'); j=h.merge(b, on='date', how='left'); print(len(h), len(b), len(j)); print(j['holiday'].notna().sum()); print(j[j['holiday'].notna()][['date','weekday','holiday','hires']].to_string(index=False))"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

手作業の結合を Python で

コード: python
# 手作業の結合です。貸出の各行が、祝日の中から自分の日付を探します。
hires = [["2025-03-19", 129], ["2025-03-20", 125], ["2025-03-21", 141]]
holidays = {"2025-03-20": "春分の日"}
for row in hires:
    name = "なし"
    if row[0] in holidays:
        name = holidays[row[0]]
    print(row[0], row[1], name)
# holidays に "2025-03-21": "金曜" を足して、もう一度実行してください。

左結合、内部結合、外部結合

内部結合は、両方の表に相手がいる行だけを残します。外部結合は、相手の有無にかかわらず、両方の表の行をすべて残します。

選び方で行数が変わり、あとで出すすべての数が変わります。どの結合を使い、なぜそれにしたかを、言葉にしてください。

結合の種類ごとに行数を数える

コマンド
docker exec jupyter python3 -c "import pandas as pd; h=pd.read_csv('hires.csv'); b=pd.read_csv('holidays.csv'); print(len(h.merge(b, on='date', how='inner')), len(h.merge(b, on='date', how='left')), len(h.merge(b, on='date', how='outer')))"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

グループに分けて、人数も読む

結合したら、問いを立てます。各日を祝日かどうかで分け、平日だけを残し、グループごとに貸出の平均を出します。

各グループに何日あるかも見ます。8日の平均は、253日の平均よりずっと弱い根拠です。

祝日と、ふつうの平日を比べる

コマンド
docker exec jupyter python3 -c "import pandas as pd; h=pd.read_csv('hires.csv'); b=pd.read_csv('holidays.csv'); j=h.merge(b, on='date', how='left'); j['is_holiday']=j['holiday'].notna(); w=j[j['weekday'].isin(['Mon','Tue','Wed','Thu','Fri'])]; print(w.groupby('is_holiday')['hires'].agg(['count','mean']).round(1))"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

キーが重なると、行が増える

2つ目の表でキーが重なると、最初の表の行は、その写し1つごとに1回ずつ書かれます。表が大きくなり、あとの合計もすべて大きすぎます。

pandas は確かめてくれます。validate="one_to_one" を渡すと、キーが一意でないときにエラーで止まります。

祝日を1つ重ねて、もう一度結合する

コマンド
docker exec jupyter python3 -c "import pandas as pd; h=pd.read_csv('hires.csv'); b=pd.read_csv('holidays.csv'); b=pd.concat([b, b.iloc[[0]]]); print(len(h.merge(b, on='date', how='left')), b['date'].is_unique)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

pandas に断らせる

コマンド
docker exec jupyter python3 -c "import pandas as pd; h=pd.read_csv('hires.csv'); b=pd.read_csv('holidays.csv'); b=pd.concat([b, b.iloc[[0]]]); h.merge(b, on='date', how='left', validate='one_to_one')" 2>&1 | tail -n 1

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

左結合なら行数は変わらない、と思いがちです。増えることがあります。左結合は最初の表の行を失いませんが、キーが重なるとその行の写しができます。結合の前と後で、行数を比べましょう。

さらに: 祝日の翌日

ノートブックで、祝日と hires.csv をもう一度結合します。祝日の翌日の、貸出の平均を出してください。

ヒント: 結合の前に、祝日の日付へ pd.to_datetime(...) + pd.Timedelta(days=1) で1日足します。先に、結果の予想を言葉にします。

このラボとソースについて: JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。