工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

pandas自分用覚書

ファイル読み取り

Excel

df = pd.read_excel(io=ファイル名, sheet_name=シート名)

CSV

# 基本形
df = pd.read_csv(ファイルパス)

# ヘッダがある
df = pd.read_csv(ファイルパス, header=0)

# 列名がないときに自分で与える
df = pd.read_csv(ファイルパス, names=[列名, ...])

# 列名をインデクス(行ラベル)として与える
df = pd.read_csv(ファイルパス, index=[列名, ...])

# Windows環境で日本語パスを含む
# https://teratail.com/questions/167493
pd.read_csv(ファイルパス, engine="python")

# 欠損値のシンボルを指定
# naという文字列が欠損値で扱われる
# 欠損値以外が数値の場合、数値列として読み込める
pd.read_csv(ファイルパス, na_values="na")

# バッファから
# バッファは、file-like objectであればいいので
# AWS boto3でclient("s3").get_objectの戻り値resp["Body"]などでもよい
df = pd.read_csv(ファイルオブジェクト)

書き出し

CSVファイル

df.to_csv(ファイルパス, index=boolean)

バッファへの書き出し

buffer = io.StringIO()
df.to_csv(buffer , index=boolean)

基本的な情報表示

# 基本統計量
df.describe(include='all') # allは質的データ(カテゴリ変数)についても計算する

# 列名の表示
df.columns

# 列のデータ型の表示
df.dtypes
# 特定データ型の列の抽出
df[df.columns[df.dtypes=データ型]]

# 項目ごとの件数を算出
df.value_counts()

# ユニークなデータ
u = データ.unique()

基本的な編集

# インデクス作成
# 行番号をカラムにする
df.reset_index()
# 指定したカラムをインデクスにする
df.reset_index(カラム)
# 古いインデクスが別の列として残る
df.reset_index(inplace=True)
# 古いインデクスを上書き
df.reset_index(inplace=True, drop=True)

# 日時関連の型変換
df[カラム名] = pd.to_datetime(df[カラム名])
df[カラム名] = pd.to_datetime(df[カラム名]).astype(型名)
df[カラム名] = pd.to_datetime(df[カラム名], format="...") # フォーマットを指定
# pandas._libs.tslibs.timestamps.Timestamp型に変換される
# df.dtypesでは、datetime64[ns]と表示される
# datetime.datetime型と同じように扱える
df[カラム名][i].date() --- 日付のみ取り出し(datetime.date型)
df[カラム名][i].day_name() --- 曜日名の取り出し
df[カラム名][i].minute --- 分の値

# 日時のオフセット
import pandas.tseries.offsets as offsets
df[カラム名] = df[カラム名] + offsets.Minute(5) # カラムはTimestamp型

# Timestamp型を文字列に戻す
df[カラム名] = df[カラム名].dt.strftime("%Y/%m/%d %H:%M:%S")


# グループ化
df.groupby(カラム名)

# ソート
df.sort_values(カラム名, inplace=True) # inplace忘れない(上書き)
# 降順
df.sort_values(カラム名, ascending=False)
# ソートされたインデクスを取得
df.sort_index(カラム名)

# 列名の割り当て
data.columns = [列名1, 列名2, ...]

# カラム名のリネーム
df.rename(columns={
    変更前のカラム: 変更後のカラム,
    :
})
  • グループ化して処理を適用
df.groupby(カラム名).apply(lambda関数)
  • 結合
pd.merge(データ1, データ2, on=カラム名, how=結合方法)

結合方法="inner"
  • データ集合
集合=set(df)
  • 積集合
集合1.intersection(集合2)
  • 条件
condition = 条件式

例えば、 df[カラム名]==3

df[condition]で、conditionを満たすものが取り出せる
  • カテゴリ変数を数値(ワンホットベクトル)に変換
dummies = pd.get_dummies(df)
  • 数値(ワンホットベクトル)をカテゴリ変数に変換(get_dummiesの逆)
sr = df.idxmax(axis=1)
  • 3値以上の数値をワンホットベクトル化
# まず文字列化
df = df.astype(str)
# get_dummies
df = pd.get_dummies(df)

DataFrame

  • numpy.ndarrayで初期化
# dataはnp.ndarray型の2次元配列
df = pd.DataFrame(data, columns=[カラム名1, ...],)
  • 空のDataFrame作成する場合

カラム名だけ与えておく

df = pd.DataFrame([], columns=[カラム名1, ...],)
  • リストを与える場合
data = [
    [v11, v12, ...],
    :
]
df = pd.DataFrame(data, columns=[カラム名1, ...])
  • 指定位置の値取り出し

    • r行c列の値を取り出す。
    • コロンですべて指定もできる
df.loc[r, c]

df.loc[r, :] # r行のすべて

df.loc[[r1, r2, ...], :] # r1, r2, ...行をすべて
  • インデクスを指定した取り出し
df.loc[インデクス]
# n1,n2行の列名1,列名2を取り出し
df.loc[n1:n2, ["列名1", "列名2"]]
  • 行番号と列番号を指定して取り出し

ilocを使う。locと異なり、インデクスの終了値を含まないことに注意。

df.iloc[行, 列]
# n1以上~n2未満の行,n3以上n4未満の列
df.iloc[n1:n2, n3:n4]
  • 先頭データの確認
df.head(行数)
  • 列(データ型)の情報
df.info()
  • サイズの確認
(行数, 列数) = df.shape # 二次元の場合
  • データ型の対応

PythonのリストなどからDataFrameにした場合

int -> np.int64
float -> np.int64
bool -> np.bool8
datetime.datetime -> np.dtype("datetime64[ns]")
str -> np.dtype("object")

# 特定のデータ型の列を抽出
df.dtypes == np.int64 # intの列だけ
  • カラム取り出し
series = df[カラム名] # 1つの列名を指定するとSeriesが返る
df2 = df[[カラム名1, カラム名2, ...]] # リストで指定するとDataFrameが返る
  • カラム削除
df.drop(カラム名, axis=1)
df.drop([カラム名1, ...], axis=1) # 複数
  • 質的データ(カテゴリ変数)の確認

    • カテゴリ変数内に出現するカテゴリ名ごとの出現数
df.value_counts()
カテゴリ名1      出現数
:                         :
Name: カテゴリ変数名, dtype: int64
  • ある列のすべての値に関数を適用
def func(x):
    :
   return 処理結果

df[列名] = df[列名].map(func)

欠損値

# 戻り値は欠損かどうか(True/False)のDataFrame
df_null = df.isnull()

# 列ごとの欠損値の数
df.isnull().sum()

# 1つでもTrueが含まれる行がTrueになる
df.isnull().any(axis=1) 

# 欠損値のある行を抽出
df[df.isnull().any(axis=1)]

# ある列で欠損値のない行のみ抽出
df = pd[~pd[列名].isnull()]

# ある列で欠損値のある行を削除
df = pd.dropna(df)
df = pd.drop(df.isnull()) # これでもいい

# 欠損値への代入
# ある列の欠損を値vで埋める
df[列名].fillna(v, inplace=上書き可否(bool)) 

重複

# 重複データの確認
# 重複行のうち、初めに見つかった方はFalse
df.duplicated()

# 重複データだけ抽出
df[df.duplicated()] 

# 重複データの削除
df.drop_duplicates(inplace=上書き可否(bool)) 

# 削除後に、インデクス振りなおし
df.reset_index(drop=True, inplace=True)

可視化

import matplotlib.pyplot as plt
df.plot(kind=グラフの種類)
df.hist() # ヒストグラム
df.hist(figsize=(w, h)) # グラフ窓の大きさ指定できる[inch]
plt.tight_layout() # グラフの軸ラベルが重ならないように表示を調整
plt.show()

DataFrameへの追加

既存のDataFrameに行を追加

df.appendメソッドを使う場合は、カラム名をキーにした辞書を与えるのが1つの方法。inplace引数は使えないので更新後のDataFrameを受け取る必要がある。ignore_index=Trueは必須。

data = {
  "カラム名1":  値,
  :
}
df = df.append(data, ignore_index=True)

DataFrame, Seriesの連結

参考

df1

a11 a12 a13
a21 a22 a23
a31 a32 a33

df2

b11 b12 b13
b21 b22 b23
b31 b32 b33

のとき

df = pd.concat([df1, df2])
# または
df = pd.concat([df1, df2], axis=0)

結合後

a11 a12 a13
a21 a22 a23
a31 a32 a33
b11 b12 b13
b21 b22 b23
b31 b32 b33
  • 列方向で連結したいとき

    df1 a11 a12 a13 a21 a22 a23 a31 a32 a33

    df2 b11 b12 b13 b21 b22 b23 b31 b32 b33

      df = pd.concat([df1, df2], axis=1)
    

    結合後

      a11 a12 a13 b11 b12 b13
      a21 a22 a23 b21 b22 b23
      a31 a32 a33 b31 b32 b33
    

DataFrameからの抽出方法いろいろ

  • あるカラムの値を指定して検索
# 抽出されなかった位置はNaNが入ったDataFrameが返る。サイズが変わらない
df2 = df[df[カラム名] == 値]

# 抽出されたものだけがDataFrameで返る。サイズが変わる
df2 = df.query('カラム名 == 値') # 文字列として渡すこと

# 条件が複数の時、&, and, |, orなど
df.query('カラム名 == 値 & カラム名 == 値') 

# 変数も使える
val = ***
df.query('カラム名 > @val')

# datetime型の列は、日時文字列でもdatetime型でも検索可能
df.query('カラム名 == "日時文字列"')
dt = datetime.datetime(...)
df.query('カラム名 == @dt')

DataFrameの一部データの削除

df = pd.drop([列名, ...])
# または
df = pd.drop([列名, ...], axis=0)
# または
df = pd.drop(index=[行名, ...])
df = pd.drop([列名, ...], axis=1)
# または
df = pd.drop(columns=[列名, ...])

相関

  • 相関行列
df.corr()

# 見づらい場合はヒートマップ(matplotlib, seaborn使用)
plt.figure(figsize=(10,8))
sns.heatmap(df.corr(), vmin=-1.0, vmax=1.0, annot=True, cmap='coolwarm', linewidths=0.1)
  • 指定したカラム同士の相関
df[[カラム名1, カラム名2]].corr()

参考