単元 4:Pandas と DataFrame 入門
- pandas をインポートし、
SeriesとDataFrameを生成できる shape/columns/dtypes/info()で DataFrame の全体像を把握できるdf["列名"]で列を、df.iloc[i]/df.loc[label]で行を、df.loc[行, 列]でセルを取り出せる- Series と DataFrame の違いを 1 行で説明できる
Pandas を使う理由
Section titled “Pandas を使う理由”Python だけでも CSV ファイルを 1 行ずつ読み込んで処理することはできます。ただし「表形式のデータ」を扱うとなると、行と列の構造を自分で管理しないといけないので、すぐに煩雑になります。
pandas は「表をオブジェクトとして扱う」ためのライブラリで、Python のデータ分析の事実上の標準になっています。CSV を 1 行で読み込み、列を指定して集計し、結果を CSV に書き戻す、という一連の操作がすべてこのライブラリ内で完結します。本コースで扱う集計・前処理・可視化はすべて pandas を中心に進めます。
Colab には pandas が最初からインストールされているので、import するだけで使えます。
import pandas as pdpd という短い別名を付けるのが慣例で、世界中のサンプルコードがこの書き方をしています。本コースでも以後 pd で統一します。
Series — 1 列ぶんの「ラベル付き配列」
Section titled “Series — 1 列ぶんの「ラベル付き配列」”pandas の最も基本的なデータ構造が Series(シリーズ) です。Python の標準のリストに似ていますが、各要素に インデックス(ラベル) がついている点が違います。
s = pd.Series([10, 20, 30], index=["a", "b", "c"])s実行すると次のように表示されます:
a 10b 20c 30dtype: int64左側の a, b, c がインデックス、右側の 10, 20, 30 が値です。値を取り出すときはラベルでアクセスできます:
s["a"] # → 10整数の位置でもアクセスできますが(s[0])、ラベルを付けられるのが Series の利点です。後で DataFrame を扱うとき、この「ラベル」が列名として活きてきます。
DataFrame — 表(複数の Series の集まり)
Section titled “DataFrame — 表(複数の Series の集まり)”実際の業務や研究では 1 列だけのデータより、Excel のシートのような 表 を扱う場面の方が圧倒的に多くなります。表は DataFrame(データフレーム) として扱います。
DataFrame は「複数の Series が縦に並んだもの」と考えると分かりやすいです。次は辞書から DataFrame を作る例:
df = pd.DataFrame({ "name": ["太郎", "花子", "一郎"], "age": [25, 30, 22], "city": ["東京", "大阪", "福岡"],})df出力:
name age city0 太郎 25 東京1 花子 30 大阪2 一郎 22 福岡辞書のキー(name, age, city)が 列名 になり、リストの中身が各列の値として並びます。左端の 0, 1, 2 は 行のインデックス(デフォルトでは整数の連番)。
全体像をつかむ 6 つの操作
Section titled “全体像をつかむ 6 つの操作”新しいデータを開いたら、いきなり中身を加工する前に まず全体像を眺めるのが定石です。次の 6 つを順番に呼ぶだけで、データの規模・列構成・型・分布の感触がつかめます。
| メソッド/属性 | 内容 |
|---|---|
df.shape | (行数, 列数) のタプル |
df.columns | 列名の一覧 |
df.dtypes | 各列のデータ型(数値か文字列か) |
df.info() | 列数・行数・型・欠損数をまとめて表示 |
df.head() | 先頭 5 行(引数で件数指定可:df.head(10)) |
df.describe() | 数値列の要約統計(平均・標準偏差・最小・最大ほか) |
実際に呼んでみると次のような流れになります:
print(df.shape) # (3, 3)print(df.columns) # Index(['name', 'age', 'city'], dtype='object')print(df.dtypes)df.info()df.head()df.describe()describe() は 数値列だけ を対象にすることに注意。文字列の列(name, city)は集計対象から外れます。
列にアクセスする
Section titled “列にアクセスする”特定の列だけを取り出す書き方は 2 つあります:
df["name"] # 1 列だけ → Series が返るdf[["name", "age"]] # 複数列 → DataFrame が返る(リストで囲む)df["name"] と df[["name"]] は 見た目が似ているが戻り値の型が違う 点に注意してください。前者は Series(1 列分のラベル付き配列)、後者は DataFrame(1 列だけの表)です。可視化など「DataFrame を渡したい」場面では後者を使い分けます。
行にアクセスする
Section titled “行にアクセスする”行を取り出すには 2 つの基本方法があります:
df.iloc[0] # 位置で取り出す:先頭行df.iloc[-1] # 末尾行df.iloc[0:2] # スライス:0 行目と 1 行目(2 行目は含まない)
df.loc[0] # ラベルで取り出す:インデックスラベルが 0 の行ilocは integer location(位置) で指定locは label(ラベル) で指定
デフォルトのインデックスは整数の連番(0, 1, 2, ...)なので両者は似た見た目になりますが、インデックスを別の値(たとえば学籍番号や日付)に振り直すと挙動が分かれます。最初のうちは「数字で当てるなら iloc、名前で当てるなら loc」と覚えておけば十分です。
セル(特定の値)にアクセスする
Section titled “セル(特定の値)にアクセスする”1 つのセルだけを取り出すなら:
df.loc[0, "age"] # 行ラベル 0、列名 "age" の値 → 25df.at[0, "age"] # 単一セルの高速版普段は loc で十分ですが、ループ内で何千回も単一セルにアクセスする場面では at の方が体感で速くなります。
よく出る躓きどころ
Section titled “よく出る躓きどころ”df["name"]とdf[["name"]]— 戻り値の型(Series か DataFrame か)が違う。可視化メソッドに渡すと挙動が変わるdf.iloc[0]とdf.loc[0]— デフォルトでは見た目が同じだが、インデックスを振り直すと別物になるdf.head()とdf.head—()を付け忘れると関数オブジェクトを返すだけで実行されない
この辺は最初は混乱しますが、3 回ほど自分で書けば自然に区別がつくようになります。
コード/スケッチ
Section titled “コード/スケッチ”- 題材データ:users.csv をダウンロード(名前・年齢・都市・性別・カテゴリ・備考の 6 列)
Drive にアップロードした users.csv を Colab で開く例:
from google.colab import drivedrive.mount('/content/drive')
import pandas as pddf = pd.read_csv("/content/drive/MyDrive/datasets/users.csv")
print(df.shape)print(df.columns.tolist())df.dtypesusers.csv を Colab に読み込み、次の操作を順番に試してください。
df.shape/df.columns/df.dtypesを表示する- 「年齢」列だけを Series として取り出して表示する
- 「名前」と「都市」の 2 列だけを DataFrame として表示する
iloc[0]で先頭行を取り出して表示するdf.loc[0, "年齢"]で「太郎の年齢」を単一値として取り出す
各操作の出力を見て、戻り値の型(Series か DataFrame か単一値か)を意識しながら進めると、本文の説明と結びつきやすくなります。
発展課題(オプション)
Section titled “発展課題(オプション)”- 辞書から自分で 5 行 4 列の DataFrame を作成し、
head()/tail()/describe()を呼んでみる df["年齢"] + 1のように Series 全体に演算をかけて、新しい列年齢_翌年を作成するdf.sort_values("年齢")で年齢順に並べ替えて表示する(次回以降の単元で詳しく扱います)