Python:外部ライブラリ(requests / pandas入門)
1学習の目的
- pip でライブラリを追加し、requests でWeb APIからデータを取得できるようになる。他社のサービスと自分のプログラムをつなげられるようになる。
- pandas で表データを読み込み、抽出・集計・並べ替えができるようになる。Excelで手作業していた分析がコード数行で終わるようになる。
2基礎解説
| やりたいこと | 書き方 | 意味 |
|---|---|---|
| ライブラリを入れる | pip install pandas | ターミナルで実行(Pythonの中ではない) |
| APIを取得する | r = requests.get(url) | r.status_code / r.json() |
| 表を作る | pd.DataFrame(辞書) | 行と列を持つ表オブジェクト |
| 集計する | df.groupby("部署")["売上"].sum() | グループごとの合計 |
- 標準ライブラリ(math / json / os)は最初から入っているが、requests や pandas は pip install が必要な外部ライブラリ。
- requests.get(url) の戻り値から、r.status_code(200なら成功)と r.json()(辞書に変換)を取り出す。
- 通信は必ず失敗しうる。timeout= を指定し、PY10の try/except で受け止めるのが必須の作法。
- pandas の基本は df["列名"] で列を取り出し、df[条件] で行を絞ること。df[df["点数"] >= 60] のように書く。
- 集計は .sum() .mean() .max()、グループ別は groupby。ループを書かずに表全体を一度に処理するのがpandasの考え方。
現場使用例:為替や天気のAPI取得、社内システムのREST API連携、売上CSVの月次集計、アンケート結果のクロス集計、Excelファイルの一括処理。
import requests
import pandas as pd
# --- requests:APIからデータを取る ---
try:
r = requests.get("https://example.com/api/users", timeout=5)
if r.status_code == 200:
data = r.json()
except requests.RequestException as e:
print(f"通信エラー:{e}")
# --- pandas:表を作って集計する ---
df = pd.DataFrame({
"名前": ["田中", "鈴木", "高橋"],
"点数": [82, 95, 67],
})
print(df.shape) # (3, 2)
print(df["点数"].mean()) # 81.33333333333333
print(df[df["点数"] >= 80]) # 80点以上の行だけ
3基本ドリル(10問)
A. math B. json C. pandas D. datetime 選択★☆☆無料
解答 == C
Pythonを入れた直後から使えるものと、そうでないもの。
C
pandas と requests は外部ライブラリで pip install pandas が必要。import でエラーが出たら、まずインストール済みか確認する。
出力 == (3, 2)
import pandas as pd してから pd.DataFrame(辞書)。行数と列数は df.shape。
import pandas as pd
df = pd.DataFrame({"名前": ["田中", "鈴木", "高橋"], "点数": [82, 95, 67]})
print(df.shape)
辞書のキーが列名、値のリストが列の中身になる。shape は (行数, 列数) のタプル。
出力 == 81.3
df["点数"].mean() で平均が取れる。表示は f"{値:.1f}"。
import pandas as pd
df = pd.DataFrame({"名前": ["田中", "鈴木", "高橋"], "点数": [82, 95, 67]})
print(f"{df['点数'].mean():.1f}")
ループも sum も len も不要。列に対してそのまま .mean() を呼べるのがpandasの発想。
____ pandas as pd
df = pd.DataFrame({"a": [1, 2, 3]})
print(len(df))
出力 == 3
モジュールを読み込むキーワード。PY12で学んだ as と組み合わせる。
import
import pandas as pd は世界共通の書き方。ネット上のサンプルコードもすべてこの形なので、必ずこれに合わせる。
A. r.status B. r.status_code C. r.code D. r.http_status 選択★☆☆無料
解答 == B
アンダースコアでつないだ2語。
B
200なら成功、404は見つからない、500はサーバー側のエラー。まず status_code を確認してから中身を読むのが基本手順。
出力 == ['田中', '高橋', '佐藤']
df[df["点数"] >= 60] で行を絞れる。名前をリストにするには list(絞った表["名前"])。
import pandas as pd
df = pd.DataFrame({
"名前": ["田中", "鈴木", "高橋", "佐藤"],
"点数": [82, 45, 91, 67],
})
passed = df[df["点数"] >= 60]
print(list(passed["名前"]))
df["点数"] >= 60 は True/False の列を作り、それを df[...] に渡すとTrueの行だけが残る。PY09の内包表記の絞り込みに相当する。
import pandas as pd
df = pd.DataFrame({"価格": [1000, 2000]})
df[____] = (df["価格"] * 1.1).astype(int)
print(list(df["税込"]))
出力 == [1100, 2200]
新しい列名を文字列で指定する。最後の print と同じ名前にすること。
"税込"
存在しない列名に代入すると列が追加される(辞書と同じ発想)。列全体に一度に掛け算できるので、ループは要らない。
A. None を返す B. 例外(ConnectionError など)が発生する C. status_code が 0 になる D. 成功するまで待ち続ける 選択★★☆無料
解答 == B
戻り値で知らせるのか、それとも別の手段か。
B
通信は必ず try/except で囲む。まとめて捕まえるなら except requests.RequestException: が便利。timeout を付けないと延々と待ち続けることもある。
出力 == {'人事': 80, '営業': 250, '開発': 320}
df.groupby("部署")["売上"].sum() で集計できる。辞書にするには .to_dict()。
import pandas as pd
df = pd.DataFrame({
"部署": ["営業", "開発", "営業", "人事", "開発"],
"売上": [100, 200, 150, 80, 120],
})
print(df.groupby("部署")["売上"].sum().to_dict())
PY07で辞書とループを使って書いた集計が1行になる。groupby の結果はキー順に並べ替えられる点に注意。
出力 == ['鈴木', '高橋']
df.sort_values("点数", ascending=False) で降順。先頭だけ取るには .head(2)。
import pandas as pd
df = pd.DataFrame({
"名前": ["田中", "鈴木", "高橋", "佐藤"],
"点数": [82, 95, 91, 67],
})
top2 = df.sort_values("点数", ascending=False).head(2)
print(list(top2["名前"]))
PY06で sorted(...)[:3] と書いたランキング処理のpandas版。行全体が一緒に並び替わるので、名前と点数の対応が崩れない。
4実践シナリオ(5問)
https://zipcloud.ibsnet.co.jp/api/search?zipcode=1000001(郵便番号検索API)にアクセスし、ステータスコードが200なら応答を辞書に変換して「取得成功:200」と出力し、続けて取得した辞書のトップレベルのキー一覧を出力せよ。通信に失敗した場合は「通信エラー:(内容)」と出力すること。
timeout=5 を必ず指定すること。 コーディング★★☆無料
接続時:取得成功:200 とキー一覧が出力される
requests.get(url, timeout=5) を try で囲み、except requests.RequestException as e: で受け止める。キー一覧は list(data.keys())。
import requests
url = "https://zipcloud.ibsnet.co.jp/api/search?zipcode=1000001"
try:
r = requests.get(url, timeout=5)
if r.status_code == 200:
data = r.json()
print(f"取得成功:{r.status_code}")
print(list(data.keys()))
else:
print(f"取得失敗:{r.status_code}")
except requests.RequestException as e:
print(f"通信エラー:{e}")
status_code を確認 → json() で辞書化 → キーを見るが、初めて触るAPIの正しい進め方。いきなり中身を決め打ちで取り出さず、まず構造を確認する。応答の中身はPY15のS05で練習した「辞書の中にリスト」の形になっている。
URLのリストに対して順にアクセスし、成功なら「[OK] URL → 200」、HTTPエラーなら「[NG] URL → 404」、通信自体が失敗したら「[ERR] URL → 内容」と出力する関数 check(url) を定義せよ。
存在しないドメインを含む2〜3件のリストで動作を確認すること(timeout=5)。 コーディング★★☆無料
各URLについて1行ずつ [OK] / [NG] / [ERR] が出力される
1件の失敗で止めないことが目的。try/except を関数の中に入れ、ループ側は淡々と回すだけにする。
import requests
urls = [
"https://zipcloud.ibsnet.co.jp/api/search?zipcode=1000001",
"https://zipcloud.ibsnet.co.jp/存在しないパス",
"https://this-domain-does-not-exist-12345.example",
]
def check(url):
try:
r = requests.get(url, timeout=5)
if r.status_code == 200:
return f"[OK] {url} → {r.status_code}"
return f"[NG] {url} → {r.status_code}"
except requests.RequestException as e:
return f"[ERR] {url} → {type(e).__name__}"
for u in urls:
print(check(u))
「HTTPエラー」と「通信できない」は別物。404はサーバーに届いたうえでの応答、ConnectionError はそもそも届いていない。監視スクリプトやクローラーはこの2つを区別して記録する。
出力4行が完全一致
保存は df.to_csv("scores.csv", index=False, encoding="utf-8")。読み込みは pd.read_csv()。合格者数は len(df[df["点数"] >= 60])。
import pandas as pd
df = pd.DataFrame({
"名前": ["田中", "鈴木", "高橋", "佐藤"],
"点数": [82, 45, 91, 98],
})
df.to_csv("scores.csv", index=False, encoding="utf-8")
loaded = pd.read_csv("scores.csv")
print(f"行数:{len(loaded)}")
print(f"平均点:{loaded['点数'].mean():.1f}")
print(f"最高点:{loaded['点数'].max()}")
print(f"合格者:{len(loaded[loaded['点数'] >= 60])}人")
PY11でcsvモジュールを使って書いた処理がread_csv の1行になる。index=False を付けないと行番号の列が余計に保存されるので忘れないこと。
「ノートPC:140,800円(送料0円)」の形式で4行出力し、最後に「送料無料:2件」と出力すること。 コーディング★★★無料
出力5行が完全一致
税込は (df["価格"] * 1.1).astype(int)。送料の列は内包表記でも作れるが、df["税込"].apply(lambda x: 0 if x >= 10000 else 800) が簡潔。出力は for _, row in df.iterrows(): で1行ずつ取り出す。
import pandas as pd
df = pd.DataFrame({
"商品": ["ノートPC", "マウス", "キーボード", "モニター"],
"価格": [128000, 3200, 8500, 45000],
})
df["税込"] = (df["価格"] * 1.1).astype(int)
df["送料"] = [0 if x >= 10000 else 800 for x in df["税込"]]
for _, row in df.iterrows():
print(f"{row['商品']}:{row['税込']:,}円(送料{row['送料']}円)")
print(f"送料無料:{len(df[df['送料'] == 0])}件")
列を足していくだけで表が育つのがpandasの気持ちよさ。iterrows() は1行ずつ取り出す方法だが遅いので、集計は必ず列単位(sum / mean / groupby)で行うこと。
出力4行が完全一致
合計は groupby("部署")["売上"].sum()、件数は .count()。合計を sort_values(ascending=False) で並べ替え、for 部署, 金額 in 並べ替えた結果.items(): で回す。
import pandas as pd
df = pd.DataFrame({
"部署": ["営業", "開発", "営業", "人事", "開発", "営業"],
"売上": [120, 200, 150, 80, 220, 90],
})
totals = df.groupby("部署")["売上"].sum().sort_values(ascending=False)
counts = df.groupby("部署")["売上"].count()
for dept, amount in totals.items():
print(f"{dept}:{amount}万円({counts[dept]}件)")
print(f"全社:{df['売上'].sum()}万円")
groupby → sort_values → items() で回すが集計レポートの定番の流れ。PY07で辞書を2つ用意して数えた処理と同じことを、宣言的に短く書けている。
5仕上げ課題
data = {
"日付": ["2026-01-05", "2026-01-08", "2026-01-12", "2026-01-15", "2026-01-20", "2026-01-22"],
"商品": ["ノートPC", "マウス", "ノートPC", "キーボード", "モニター", "マウス"],
"部門": ["法人", "個人", "法人", "個人", "法人", "法人"],
"金額": [128000, 3200, 128000, 8500, 45000, 3200],
}
仕様:
① DataFrame を作り "sales.csv" に保存(index=False)→ read_csv で読み込む
② 全体の件数・総売上・平均単価(カンマ区切り整数)を出力
③ 商品別の売上合計を多い順に出力
④ 部門別の売上合計を出力(groupbyの既定順)
⑤ 最高額の取引の商品名と金額を出力
出力仕様(14行):
=== 売上分析レポート ===
取引件数:6件
総売上:315,900円
平均単価:52,650円
---
[商品別]
ノートPC:256,000円
モニター:45,000円
キーボード:8,500円
マウス:6,400円
---
[部門別]
個人:11,700円
法人:304,200円
---
最高額:ノートPC(128,000円)
出力16行が完全一致
商品別は groupby("商品")["金額"].sum().sort_values(ascending=False)、部門別は並べ替えなしでそのまま .items() で回す。最高額の商品名は df.loc[df["金額"].idxmax(), "商品"] で取れる(idxmax は最大値の行番号を返す)。
import pandas as pd
data = {
"日付": ["2026-01-05", "2026-01-08", "2026-01-12", "2026-01-15", "2026-01-20", "2026-01-22"],
"商品": ["ノートPC", "マウス", "ノートPC", "キーボード", "モニター", "マウス"],
"部門": ["法人", "個人", "法人", "個人", "法人", "法人"],
"金額": [128000, 3200, 128000, 8500, 45000, 3200],
}
pd.DataFrame(data).to_csv("sales.csv", index=False, encoding="utf-8")
df = pd.read_csv("sales.csv")
print("=== 売上分析レポート ===")
print(f"取引件数:{len(df)}件")
print(f"総売上:{df['金額'].sum():,}円")
print(f"平均単価:{df['金額'].mean():,.0f}円")
print("---")
print("[商品別]")
by_item = df.groupby("商品")["金額"].sum().sort_values(ascending=False)
for item, amount in by_item.items():
print(f"{item}:{amount:,}円")
print("---")
print("[部門別]")
by_dept = df.groupby("部門")["金額"].sum()
for dept, amount in by_dept.items():
print(f"{dept}:{amount:,}円")
print("---")
best = df.loc[df["金額"].idxmax()]
print(f"最高額:{best['商品']}({best['金額']:,}円)")
PY11では60行かけて書いた集計が、pandasでは30行足らずで、しかも分析軸を増やすのが groupby 1行で済む。「商品別も見たい」「部門別も見たい」という要望に即応できるのがデータ分析ツールの価値。ここまでで、CSVを渡されたら読み込んで集計しレポートを出す、という実務のデータ処理が一通りできるようになった。次の一歩は matplotlib でのグラフ化や Excel 出力(openpyxl)だが、土台はすでに完成している。