😽

Pythonでデータ前処理

に公開

Pythonのpandasでデータの前処理をする際に、よく使用するコードをまとめてました。

ライブラリの読み込み

import pandas as pd
import numpy as np 
import os 
from glob import glob

pandas(データ分析用)、numpy(数値計算用)などのライブラリを読み込みます。os や glob はファイル操作でよく使われる標準ライブラリです。

# pandas の表示設定
pd.options.display.max_columns = None          # すべての列を省略せずに表示
pd.options.display.notebook_repr_html = True   # DataFrameをHTML(表)形式で表示

この設定をすることで、Jupyter Notebookなどでデータの中身をきれいに表示できます。

ファイル検索

glob()

  • 特定パターンにマッチするファイルパス一覧を取得
    → 複数のCSVファイルやExcelファイルを一括処理したいときに便利!
csv_files = glob('data/*.csv')
# dataフォルダ内のファイル名の末尾が".csv"であるファイルパスをリスト形式で取得

あるフォルダ内のCSVファイルをすべて読み込んで1つのDataFrameにまとめるには以下のコードのように簡潔に書くことができます!

# CSVファイルの一覧を取得
file_list = glob('data/*.csv')

# 各ファイルを読み込んで1つのDataFrameにまとめる
df_all = pd.concat([pd.read_csv(file) for file in file_list], ignore_index=True)

display(df_all)

CSVファイルの読み込み

pd.read_csv()

  • 主にCSVファイルをDataFrameとして読み込む
df = pd.read_csv('data.csv',       # csv ファイルのパスを指定
                 index_col=None,   # インデックスとして使用する列の番号or名前を指定
                 header=3)         # ヘッダーの行数を指定

pd.read_csv()のよく使用する引数まとめ

引数名 説明
delimiter 区切り文字。(デフォルトは ',''\t' でタブ区切り。)
header 列名として使用する行番号(デフォルトは最初の行)
index_col 行インデックスとして使う列(列名 or 番号)
skiprows 読み飛ばす先頭の行数 or 行番号のリスト
skipfooter 読み飛ばす末尾の行数
nrows 読み込む行数(先頭から)
names 列名のリストを指定
usecols 読み込む列番号 or 列名
dtype 列ごとの型指定:{'col1':'int', 'col2':'object'} など
encoding 文字コード(デフォルトは 'utf-8''shift-jis', 'cp932'など)
engine CSV読み込みエンジン(デフォルトは 'c'、問題時は 'python'

基本的な情報取得系メソッド

読み込んだ直後はまずこれらで「どんなデータか」を確認します。

head()

  • 先頭行を表示
df.head()

tail()

  • 末尾行を表示
df.tail(10)

shape

  • 行数と列数のタプルを返す
df.shape

describe()

  • 数値データの要約統計量(平均、標準偏差など)を表示
  • include='all' で全列対象
df.describe(include='all')

info()

  • データ型、欠損値、行数などの基本情報を表示
df.info()

データ型・ユニーク値の確認

このあたりは、カテゴリの確認や、後の前処理・集計に向けた準備段階です。

dtype

  • データ型を確認
df.dtypes

unique()

  • シリーズ(1列)のユニークな値を取得
df['Sex'].unique()

nunique()

  • シリーズ(1列)のユニークな値の個数を取得
df['Sex'].nunique()

value_counts()

  • Series内のユニークな値の出現回数をカウント
  • normalize=True で出現比率(割合)を返す
  • sort=False で出現順で並べる
  • bins=n で数値データをn個の等間隔のビン(区間)に分けて集計
df['Sex'].value_counts()

データの保存・列操作・型変換

列を選んだり、名前を変えたり、数値型に直すなどの「前処理」に必須。

to_csv()

  • CSVファイルとして保存
  • index=False でインデックスを保存しない
df.to_csv('data.csv',
          index=False)        # インデックスを保存しない

df[['列1', '列2']]

  • 複数列の抽出
df[['Name', 'Age']]

rename()

  • 列名や行名を変更
df.rename(columns={'名前':'Name'})

astype()

  • データ型を変換
df['Age'] = df['Age'].astype(int)

文字列の処理

str[]

  • 文字列を抽出
df['Name'].str[:2]

str.contains()

  • 指定した文字を含むデータを抽出
df['Name'].str.contains("山田")

値の変換・欠損処理・列削除

データの品質を整えるためのクリーニング操作です。

replace()

  • 値の置換
df['Sex'].replace({'男': 1, '女': 0})

fillna()

  • 欠損値を補完
  • method='ffill'で1つ前の行の値、'bfill'で1つ後ろの行の値で補完
df.fillna(0)                      # 0で補完
df['Sex'].fillna(method='ffill')  # 1つ前の行の値で補完

drop()

  • 行または列を削除
  • axis=0 で行方向、 1 で列方向
  • inplace=True で元のデータを書き換える
df.drop('Age', axis=1, inplace=True)

dropna()

  • 欠損値を含む行や列を削除
  • axis=0で行方向、axis=1で列方向で欠損値を削除
  • how='any' で欠損値が一つでも含まれる行が削除(デフォルト)、
    'all' ですべての値が欠損値の行が削除
  • subset=['列名']で指定したカラムがNaNである場合に削除
df.dropna()

並び替え・集計・重複の処理・グルーピング

表として見やすくする・上位を抽出するなどの目的でよく使います。

sort_values()

  • 指定した列で並び替え
  • ascending=Trueで昇順、Falseで降順
df.sort_values(by='Score', ascending=False)    # 得点カラムを降順で並び替え

reset_index(drop = True)

  • インデックスをリセットする
df.sort_values(by='Score', ascending=False).reset_index(drop=True)

rank()

  • 順位をつける
  • ascending=Trueで昇順、Falseで降順
  • ランクが同一だった場合の順位の割り振りは、method='min' で最小順位を割り付ける。ほかにも max, average, first がある。
df['Ranking'] = df['Score'].rank(ascending=False)

duplicated()

  • 重複の有無を判定(True/FalseのSeries)

drop_duplicates()

  • 重複行を削除
  • subset で削除する列名を指定
  • keep='first' で最初だけ残す、
    'last' で最後だけ残す、
    False ですべて削除
  • inplace=True で元のデータを書き換える
df.drop_duplicates(subset='Name', keep='last')

groupby()

  • グルーピングして集計
df.groupby('Grade')['Score'].mean()

変化・累計

時間の経過や変化を見るときに便利な計算です。

shift()

  • 指定した行数前の値を取得
df['Last'] = df['Score'].shift(1)

diff()

  • 指定した行との差を計算
df['Difference'] = df['得点'].diff()

pct_change()

  • 前の行との変化率(%)を計算
df['Rate_of_change'] = df['Sales'].pct_change()

cumsum()

  • 累積合計
df['Cumulative'] = df['Sales'].cumsum()

条件・フィルタリング

フィルタリングや新しい列の作成に便利です。

isin()

  • リストに含まれるかどうかでフィルタリング
df[df['Prefecture'].isin(['東京', '大阪'])]

isna()

  • 欠損値(NaN)かどうかを判定し、True / False のブール値を返す
df["Age"].isna() 

np.where()

  • 条件分岐
df['Grade'] = np.where(df['Score'] >= 60, '合格', '不合格')

結合・変換

pd.concat()

  • データフレームの縦横結合
  • axis=0(デフォルト)で縦結合、axis=1で横結合
  • ただし、横結合は次の pd.merge() を使ったほうが良き。
df_new = pd.concat([df1, df2])

pd.merge()

  • データフレーム同士をキーで横結合
  • on='列名'でキー指定。
  • 結合するデータフレームで列名が異なる場合は、
    left_on='左から結合するdfの列名', right_on='右から結合するdfの列名'
  • 結合方法は、
    how='inner' で自然結合、how='left' で左結合など
  • suffixes=() で列名の接尾辞の指定が可能
pd.merge(df1, df2, on='ID', how='left')

pd.melt()

  • ワイド形式をロング形式に変換(列→行)
  • id_vars で基本軸(変換の際に固定する列)となる列名を指定
  • value_vars で変換の際に移動する列名を指定
  • value_name で新規列名を指定
pd.melt(df, id_vars=['ID'], var_name='Subject', value_name='Score')

前処理あとの流れ

このように、pandasでは「読み込み → 前処理 → 分析 → 出力」まで一連の流れをすべてPythonで行うことができます。

前処理を行った後は、データを可視化したり、機械学習などでデータ分析していきましょう!

参考文献

より詳しく知りたい方は以下をどうぞ。

https://amzn.to/3Gf2Fnd

https://amzn.to/3Rt45gj

Discussion