1年分の貸出記録に聞きたいこと
あるレンタサイクル店は、1日に1行ずつ、1年分の記録を残しています。店長には知りたいことが2つあります。週末は本当に忙しいのか。とても忙しかった日は何日あったのか。
365行を目で追っても、答えは出ません。pandas を数行書けば、数秒で答えが出ます。
このレッスンのゴール
メモ
データの表を読み込み、その表に質問できる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| DataFrame | pandas の表で、列に名前がついたもの | |
| 列 | すべての行に共通する、名前のついた項目 | hires["temp_c"] |
| 絞り込み | 条件に合う行だけを残すこと | hires["hires"] > 400 |
| グループ化 | ある列の値ごとに行を分けること | groupby("weather") |
| 集計 | たくさんの値を、平均などの1つの値にまとめること | |
| 中央値 | 値を順に並べたときの真ん中の値 | |
| 最頻値 | いちばん多く現れる値 |
学生が入力するセルは、このプレビューでは空白です。
ラボへの2つの入り口
レッスンのバーで起動を押し、ラボが動き出すまで待ちます。横のターミナルには Python がありません。実行ボタンは docker exec jupyter と入力し、ラボのコンテナの中でコマンドを1つ動かします。
ノートブックは、バーから JupyterLab を開いて使います。「ノートブックに入力」という題のブロックは、新しいセルに打ち込みます。このページの Python には pandas がないので、ここでは動きません。
DataFrameは列に名前がある表
pd.read_csv は、CSVファイルを DataFrame に読み込みます。列の名前は、ファイルの1行目から来ます。この表の列名は英語で、weather は天気、hires は貸出台数です。
角かっこに名前を入れると、1つの列を選べます。hires["rain_mm"] は毎日の雨の量です。列には max、mean、value_counts などのメソッドがあります。
ファイルの先頭を見る
docker exec jupyter head -n 3 hires.csvここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ノートブックに入力: 1つの列
import pandas as pd
hires = pd.read_csv("hires.csv")
# 1年でいちばん多かった雨の量(mm)です。
hires["rain_mm"].max()
貸出台数をまとめて見る
docker exec jupyter python3 steps/summary.pyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
絞り込みは条件に合う行を残す
hires["hires"] > 400 は、すべての行に同じ質問をします。答えは True と False が並んだ列です。
この答えを hires[...] の中に入れると、True の行だけが残ります。2つの条件をつなぐときは、「かつ」に &、「または」に | を使います。条件はそれぞれかっこで囲みます。
とても忙しかった日を数える
docker exec jupyter python3 steps/filter.pyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ノートブックに入力: 2つの条件
# 5度未満なのに、250台を超えた日です。
cold_busy = hires[(hires["temp_c"] < 5) & (hires["hires"] > 250)]
len(cold_busy)
よくある間違い
注意
pandas でも Python の and で条件をつなげると考えがちです。and は True か False を1つだけ求めますが、列の条件は365個の答えを返します。そのため pandas は「The truth value of a Series is ambiguous」と止まります。& を使い、条件をかっこで囲んでください。
groupbyは分けてからまとめる
hires.groupby("weekday")["hires"].mean() は3つのことをします。曜日ごとに行を分けます。各グループの hires 列を選びます。それぞれの平均を出します。
平均は、極端な日に引っぱられます。中央値は引っぱられにくいので、両方を見ます。天気のような言葉の列には、最頻値が合います。
例: 大きな1日があると
| データ | 平均 | 中央値 | 最頻値 |
|---|---|---|---|
| 210, 185, 330, 185, 245, 200, 480 | 1835 / 7 = 262.1 | 210(7つの4番目) | 185(2回) |
| 480 を除いた6日 | 1355 / 6 = 225.8 | (200 + 210) / 2 = 205 | 185(2回) |
学生が入力するセルは、このプレビューでは空白です。
平均と中央値を手で求める
# ある駅の貸出台数、7日分です。
days = [210, 185, 330, 185, 245, 200, 480]
total = 0
for one in days:
total = total + one
print("平均:", round(total / len(days), 1))
in_order = sorted(days)
middle = len(in_order) // 2
print("中央値:", in_order[middle])
# 480 をリストから消して、もう一度実行してください。
# 平均と中央値、大きく動くのはどちらですか。
週末と平日を比べる
docker exec jupyter python3 steps/weekend.pyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ノートブックに入力: 曜日ごと
# 曜日ごとの平均を、少ない順に並べます。
hires.groupby("weekday")["hires"].mean().round(1).sort_values()
さらに挑戦: 月ごとの中央値
ノートブックで、中央値がいちばん小さい月を探してください。month でグループ化し、hires の中央値を出し、sort_values で並べます。
次に、絞り込みとグループ化を両方使う質問を自分で1つ作ります。たとえば、雨の日だけでも週末は忙しいでしょうか。実行する前に、答えを予想して書いておきましょう。