アットウィキロゴ

トップページ > コンテンツ > 機械学習関連 > 機械学習のライブラリ > pandas


0.pandasの導入

インストール手順等は割愛する。ぱっと試すのであれば、googleアカウントがあればすぐ使える
Colaboratoryが便利。必要なライブラリをインポートしてから試す。
import numpy as np
import pandas as pd

1.SeriesとData Frameの概念

Seriesは1次元のラベル付きデータ構造で、DataFrameは2次元のラベル付きデータ構造である。

2.Seriesの基本

pd.Series(データ,index=データと同じ長さのインデックス)の形で作成する。
s = pd.Series([1, 2, 3], index=["a", "b", "c"])

3.データの読み込み

3-1.DataFrame作成

3-1-1.変数データ読み込み

data =  {
    "名前":["佐藤","鈴木","高橋"],
    "性別":["男性","女性","男性"],
    "年代":[20,30,40]
}

df = pd.DataFrame(data)

3-1-2.csvファイル読込

df = pd.read_csv("csvファイル名",header =0,usecols=[使用する行],index_col=データの名称が書かれた列)
のような感じで読み込めた。

詳細は、こちらのサイトを見た方が早いので、メモ書きのみ。

4.データ確認

4-1.データの基本情報確認

df.shape 行列数を表示。df.shape[0]が行数、df.shape[1]が列数になる
len(df) 行数を知りたい場合の書き方
len(df.columns) 列数を知りたい場合の書き方
df.columns 列名のリストを表示。列名のリストでループ処理回したり、イコールで新しい列名を代入させることも可能。
df.head(数値) 数値で指定した分の先頭行を表示
df.tail(数値) 数値で指定した分の末尾行を表示
df.dtypes 「カラム名→型」の対応をSeriesとして表示
df.info() データフレームの概要(列名、非欠損値の数、データ型、メモリ使用量)を表示
df.describe() 数値型列の統計情報(平均、標準偏差、最小値、最大値など)を表示


5.データ追加・削除・変更

5-1.行追加

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df.loc[3] = ["渡辺","女性",30]

5-2.列追加

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df["住所"] = ["東京","京都","大阪"]

5-3.行削除

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df = df.drop(0) 

#ちなみに重複削除等の場合は以下のようにする。
df = pd.DataFrame({"名前":["佐藤","鈴木","佐藤"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df = df.drop_duplicates(subset="名前")

5-4.列削除

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df = df.drop("性別",axis=1) 

※上記はdropで削除後の新しいデータフレームを返しているが、
 元のdfに直接作業させるという意味では、del df['性別']という書き方もある。

5-5.行更新

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df.loc[1] = ["渡辺", "女性", 50]

5-6.列更新

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df["性別"] = "女性"

5-7.列名更新

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df = df.rename(columns={"名前":"姓名"})

6.データの選択と参照

6-1.行選択、複数行選択、スライシング

  • 行選択
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df.iloc[0] #最初の行を選択。df.iloc[0, :]と同義。

  • 複数行選択
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df.iloc[[0,2]] #1行目と3行目を選択

  • スライシング
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df.iloc[1:3] #最初の値は含まれるが、最後の値は含まれない。つまり1〜2まで切り取る。
        行数で見た場合は0が1行目なので、2・3行目を切り取るような記述になる。

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]},index=["A","B","C"])のようにラベル付きでデータフレーム定義をしている場合は、
df.loc["A":"C"]のように指定することもできる。

6-2.列選択、複数列選択、スライシング

  • 列選択
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df["名前"]

  • 複数列選択
df[["名前","性別"]]

  • スライシング
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df.iloc[:, 1:3] #2・3列目を切り取るような記述。

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df.loc[:, "列名1":"列名3"]

6-3.loc[]とiloc[]について

記法 説明 備考
df.loc[行の範囲,列の範囲] ラベルベースでデータにアクセスする方法 スライスで(開始位置:終了位置)を指定する際に終了位置も含む
df.iloc[行の範囲,列の範囲] 整数位置ベースでデータにアクセスする方法 スライスで(開始位置:終了位置)を指定する際に終了位置は含まない。番号付けは0から始まるので、例えば行の所で「0:2」のように指定すると1行目から2行目のデータという意味になる

:は全ての行または列を表現するものとしてよく使われるので覚えておきたい。

6-4.データのフィルタリングと条件付き選択

6-4-1.条件で選択

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df[df["年代"] > 30]

6-4-2.フィルタリング

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
selction = (df["年代"] > 30) & (df["性別"] == "男性")
df[selction]

6-4-3.条件を使った行と列の部分指定選択

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df.loc[(df["名前"]=="佐藤"),"年代"]

6-4-4.ブール型インデックスの使用(真偽値のこと)

値を含んでいるかの包含チェックができる。
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df[df["名前"].isin(["佐藤", "鈴木"])]

7.データの変形と整形

7-1.データ型の変換

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df["年代"] = df["年代"].astype(float)
df["年代"].dtype #変換されたか確認

7-2.欠損値の処理

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,np.nan,40]})
df = df.fillna(0) #0で補完する場合
df = df.dropna(subset="年代") #削除する場合
※欠損値か否かはdf['列名'].isnull()のようにすることで確認できる。 

7-3.データのダミー化(文字列データを数値に変えたりする)

df = pd.DataFrame({"名前":["佐藤","鈴木","佐藤"],"性別":["男性","女性","その他"],"年代":[20,30,40]})
df['性別_ダミー'] = df['性別'].map({'男性': 0, '女性': 1}) #性別を0と1に置き換えた。
df_dummies = pd.get_dummies(df, columns=['性別']) #種類ごとにTrue,Falseが入る。One-Hotエンコーディング処理を行うことができる。

7-4.melt()とpivot()の使用

  • melt:複数の列を1つの列にまとめる(例:性別と年代を属性情報にまとめる場合)
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df_melted = df.melt(id_vars=["名前"], var_name="属性", value_name="値")

  • pivot:melt関数の逆を行う。
df_pivoted = df_melted.pivot(index="名前", columns="属性", values="値")
df_pivoted = df_pivoted.reset_index()
df_pivoted.columns.name = None

8.データの集計と分析

8-1.グループ化

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋"],"性別":["男性","女性","男性"],"年代":[20,30,40]})
df_grouped = df.groupby("性別") 
df_grouped.get_group("男性") #グループのデータの中身を見る場合。性別でグルーピングして、男性の物のみ表示

8-2.集計関数の利用

#グループ化のコマンドを実行していること
df_grouped["年代"].mean() #グループ化した内容で集計情報を出す場合

8-3.ピボットテーブル

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋","鈴木"],"性別":["男性","女性","男性","女性"],"年代":[20,30,40,50]})
pivot_table = pd.pivot_table(df, values="年代", index=["性別"], columns=["名前"], aggfunc=np.mean) #年代で集計する。行は性別、列は名前毎になるイメージ

8-4.データの結合とマージ

8-4-1.結合(inner, outer, left, right)

# 適当なサンプルデータ例(ユーザの基本情報)
df_basic = pd.DataFrame({
   "ユーザ番号": [1, 2, 3, 4, 5],
   "性別": ["男", "女", "男", "女", "男"],
   "年齢": [25, 30, 35, 28, 40],
   "名前": ["佐藤", "鈴木", "田中", '高橋', "渡辺"]
})

# 適当なサンプルデータ例(ユーザの追加情報)
df_additional = pd.DataFrame({
   "ユーザ番号": [2, 3, 4, 5, 6],
   "住所": ["東京都", "大阪府", "愛知県", "福岡県", "北海道"],
   "誕生日": ['1993-05-15', '1988-11-30', '1995-08-22', '1983-02-10', '1990-07-07']
})

#内部結合の場合
result_inner = pd.merge(df_basic, df_additional, on="ユーザ番号", how="inner")

#外部結合の場合
result_outer = pd.merge(df_basic, df_additional, on="ユーザ番号", how="outer")

#左結合の場合
result_outer = pd.merge(df_basic, df_additional, on="ユーザ番号", how="left")

#右結合の場合
result_outer = pd.merge(df_basic, df_additional, on="ユーザ番号", how="outer")

8-4-2.concat()の使用

時系列データを連結する等、キーを指定せずに複数のDataframeを連結する時には、concat関数を使うことができる。
縦につなぐ場合はindex番号は連結前のデータフレームの番号を維持し、
連結後にindex番号を振り直してくれるとかはないため注意。

# 縦方向(行方向)の結合
result_vertical = pd.concat([df1, df2])

# 横方向(列方向)の結合
result_horizontal = pd.concat([df1, df2], axis=1)

8-5.データのソートと並べ替え

8-5-1.単一列でのソート

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋","鈴木"],"性別":["男性","女性","男性","女性"],"年代":[20,30,40,50]})
df_sorted = df.sort_values("性別")

8-5-2.複数列でのソート

df = pd.DataFrame({"グループ番号":["0002","0001","0001","0001"],"名前":["佐藤","鈴木","高橋","鈴木"],"性別":["男性","女性","男性","女性"],"年代":[50,40,30,20]})
df_sorted = df.sort_values(["グループ番号","年代"])

8-6.高度なデータ操作

8-6-1.apply()とapplymap()の使用

各行や各列に対して、計算処理を適用する場合はapply関数を使うと良い。
apply間数は各行や各列に対して、繰り返し同じ関数を呼び出して、計算処理を適用するようなイメージになる。

全セルに対して、計算処理を適用したいような場合はapplymapを使うと良い。ここではapplyの例だけ記載する。

import math
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋","鈴木"],"性別":["男性","女性","男性","女性"],"年齢":[25,34,44,55]})
df["年代"] = df['年齢'].apply(lambda x: math.floor(x / 10) * 10) #今回は単純な変換なのでlambda式を用いたが、複雑な加工処理になる場合は独自関数を用意して関数を指定すると良い。

ただし、apply関数は毎回呼び出すため、若干動作が遅い。
特定の内容で分岐させるなら、np.whereやlocによるベクトリ処理とかも考えると良い。
df = pd.DataFrame({"年齢":[25,34,44,55], "性別":["男性","女性","男性","女性"]})

# 遅いapply版(避ける)
df['カテゴリ'] = df['年齢'].apply(lambda x: '未成年' if x < 18 else '成人')

# 高速np.where版(全行更新)
df['カテゴリ'] = np.where(df['年齢'] < 18, '未成年', '成人')

# 高速loc版(部分更新)
df.loc[df['年齢']<18, 'カテゴリ'] = '未成年'

8-6-2.ループ処理と効率的な代替手段

一般的なループ処理はfor文を回す。
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋","鈴木"],"性別":["男性","女性","男性","女性"],"年齢":[25,34,44,55]})

#行方向のループ例
for i in range(len(df)):
    df.loc[i, "年齢"] = df.loc[i, "年齢"]+1

#列方向のループ例
for col in df.columns:
   print(df[col])

#列方向のループ例
for col_name, col_data in df.items():
   print(col_name)
   print(col_data)

for文を回すと遅くなりがちというデメリットがあるため、ベクトル演算等の利用も考えると良い。
行方向の処理について、もっと効率的に表現するには以下のようにする。
df["数え年"] = df["年齢"]+1
df["未成年"] = df["年齢"]<18

8-6-3.時系列データの扱い

日付情報を付与するには、date_rangeを使うと良い。
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋","鈴木"],"性別":["男性","女性","男性","女性"],"年齢":[25,34,44,55]})
df["データ生成日"] = pd.date_range(start="2025-01-01", end="2025-01-01",periods=len(df))
df.set_index("データ生成日", inplace=True)

8-6-4.データの出力と可視化

データの可視化を行うにはmotplotlibを使うと良い。
以下の例は棒グラフの例だが、散布図、ヒストグラム等色々な物が用意されている。
import matplotlib.pyplot as plt
df = pd.DataFrame({"名前":["佐藤","鈴木","高橋","鈴木"],"性別":["男性","女性","男性","女性"],"年齢":[25,34,44,55]})
df["年齢"].plot(kind='bar')
plt.show()

8-6-5.データの書き出し(CSV, Excel等)

df = pd.DataFrame({"名前":["佐藤","鈴木","高橋","鈴木"],"性別":["男性","女性","男性","女性"],"年齢":[25,34,44,55]})
df.to_csv('output.csv', index=False)
最終更新:2025年12月14日 17:13