【このページは現在作成中です】
#準備(すべてに共通) # PandasとNumpyをインポート import pandas as pd import numpy as np # 日本語化Matplotlibもインポート import matplotlib.pyplot as plt !pip install japanize-matplotlib import japanize_matplotlib # Seabornもインポート import seaborn as sns # pickleをインポート(モデルの保存用) import pickle # データの取得 data = pd.read_csv("https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/bike-sharing-day.csv") data
データが構造化された表にちゃんと収まっているかを確認する
df.shape
df.dtypes df.info()
df.isnull().sum()
df["列1"].value_counts()
分析用のデータセットの作成に向けて,データの型やインデクスを整えていく
df = data.copy()
#列を任意の型変換する df["列1"] = df["列1"].astype("型名") #日時型への変換 df["日時列2"] = pd.to_datetime(df["日時列2"])
df.set_index("列1", inplace=True)
df.drop(columns=["列1", "列2", ...], inplace=True)
#先頭数行の値を確認 data.head()
#型を確認 data.info()
#オリジナルデータをコピーして作業 df = data.copy()
#dtedayを日付型に変換 df["dteday"] = pd.to_datetime(df["dteday"]) #確認 df.info() df
#season, holiday, weekday, workingday, weathersitをカテゴリ型に変換 for col in ["season", "holiday", "weekday", "workingday", "weathersit"]: df[col] = df[col].astype("category") #確認 df.info() df
#dtedayをインデクスに設定して時系列データにする df.set_index("dteday", inplace=True) #確認 df.info() df
#instant, yr, mnth: 冗長なので削除 df.drop(columns=["instant", "yr", "mnth"], inplace=True) #確認 df.info() df
様々な観点からデータを探索(要約・可視化)して,データが持つ性質を理解する
可視化にはpythonのライブラリを使う
df.describe()
df["列1"].value_counts()
df.plot.box() sns.boxplot(df) #Seabornを使う場合
df["列1"].plot.hist() sns.histplot(df["列1"]) #Seabornを使う場合
sns.violinplot(df)
df.plot.bar() sns.barplot(df) #Seabornを使う場合
df["列1"].plot() df["列1"].resample("周期").集約関数().plot() #週や月で時系列を集約して表示する場合 sns.lineplot(df) #Seabornを使う場合
#describe()は基本的に数値列のみを要約する df.describe()
#カテゴリの列を要約 for col in ["season", "holiday", "weekday", "workingday", "weathersit"]: print(f"\n【{col}の要約】") print(df[col].value_counts())
#気象データの分布を箱ひげ図で可視化 sns.boxplot(df[["temp", "atemp", "hum", "windspeed"]])
#利用者データの分布を箱ひげ図で可視化 sns.boxplot(df[["casual", "registered", "cnt"]])
#各変数のヒストグラムを描いてみる.サブプロットを使って,1枚の図に並べる fig, axes= plt.subplots(nrows=4, ncols=2, tight_layout=True, squeeze=False) for i, col in enumerate(["temp", "atemp", "hum", "windspeed", "cnt", "casual", "registered"]): sns.histplot(df[col], ax=axes[i//2, i%2], bins=40)
#利用者データの推移を見てみる fig, axes = plt.subplots(nrows=2, ncols=1, tight_layout=True, squeeze=False, figsize=(6,8)) #利用者データの推移 df[["casual", "registered", "cnt"]].plot(ax=axes[0,0], title="利用者データの推移(日次)") #利用者データの月ごとの推移を棒グラフで(登録・都度の内訳) df[["casual", "registered"]].resample("M").sum().plot.bar(stacked=True, ax=axes[1,0], title="利用者データの推移(月次)")
df.corr() sns.heatmap(df.corr(), annot=True) #ヒートマップで可視化する
df.plot.scatter(x=列1, y=列2) sns.scatterplot(df, x=列1, y=列2, hue=列3) #Seabornを使う場合.hueで色分けできる
sns.pairplot(df) #変数が多いと時間がかかるし見づらい
#相関係数を求める df.corr()
#カテゴリ変数も含めたければ,get_dummies()を行う pd.get_dummies(df).corr()
#ヒートマップで可視化 sns.heatmap(df.corr(), annot=True)
#気温と総利用者数の関係.季節で色分け sns.scatterplot(df, x="temp", y="cnt", hue="season")
#ペアプロット sns.pairplot(df)
df.groupby("カテゴリ列1").describe()["数値列2"]
【比較の観点】
#統計量の要約 df.groupby(df.index.year).describe("cnt") df.groupby("season").describe("cnt") #以下同様 # : #箱ひげ図で比較する fig, axes = plt.subplots(nrows=4, ncols=2, figsize=(18,18)) sns.boxplot(df, y="cnt", x=df.index.year, ax=axes[0,0]) sns.boxplot(df, y="cnt", x="season", ax=axes[0,1]) sns.boxplot(df, y="cnt", x=df.index.month, ax=axes[1,0]) sns.boxplot(df, y="cnt", x="weekday", ax=axes[1,1]) sns.boxplot(df, y="cnt", x="holiday", ax=axes[2,0]) sns.boxplot(df, y="cnt", x="workingday", ax=axes[2,1]) sns.boxplot(df, y="cnt", x="weathersit", ax=axes[3,0])
#バイオリンプロットでもやってみてください # 略
df.isnull().sum() #列ごとの欠損値の数を数える df[df["列1"].isnull()] #列1が欠損している行を抜き出す
df = df.dropna() df = df.dropna(subset=[列1, 列2, ...]) #特定の列のNaNのみを対象
df = df.fillna(0)
df = df.fillna(df.集約関数()) #表全体 df["列1"] = df["列1"].fillna(df["列1"].集約関数()) #列ごと
df = df.fillna(method="ffill" または "bfill") #表全体 df["列1"] = df["列1"].fillna(method="ffill" または "bfill") #列ごと
df = df.interpolate() #表全体 df["列1"] = df["列1"].interpolate() #列ごと
# 箱ひげ図や散布図から見つける
df = df.drop(index=[行1, 行2, ...])
df.loc[行1, 列1] = 正しい値
df[df.duplicated(keep=False)]
df = df.drop_duplicates()
#クリーニングされていないシェアサイクルのデータをロード data = pd.read_csv("https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/bike-sharing-unclean.csv") #コピーしておく df = data.copy()
#欠損値の個数を数える df.isnull().sum()
#tempが欠損している行を抜き出す df[df["temp"].isnull()]
#前後を見てみる df[185:195] #行ごと削除する (dfに代入していないので,dfはそのまま) df.dropna(subset=["temp"])[185:195]
#定数0で埋める (dfに代入していないので,dfはそのまま) df.fillna(0)[185:195]
#中央値で埋める (dfに代入していないので,dfはそのまま) df.fillna(df.median())[185:195]
#線形補間で埋める (dfに代入していないので,dfはそのまま) df.interpolate()[185:195]
#すべての欠損値を線形補間で埋める df = df.interpolate()
#欠損値を数える df.isnull().sum()
#要約統計量を求める df.describe()
#怪しそうな変数を表示する df[["casual", "registered", "cnt"]].plot.box() #条件で特定してみる df[df["cnt"] > 80000]
#周辺のデータを見てみる df[510:520]
#修正する df.loc[517, "casual"] = 533 df.loc[517, "cnt"] = 4127
#再度箱ひげ図で確認 df[["casual", "registered", "cnt"]].plot.box()
#重複行を見つける df[df.duplicated(keep=False)]
#重複行を削除する df = df.drop_duplicates()
#重複行を再度確認 df[df.duplicated(keep=False)]
pd.get_dummies(df, columns=[ダミー変数化する変数のリスト], drop_first=True)
#元データを適当に作る df = pd.DataFrame(data={"物件No.":[1,2,3,4,5], "駅からの距離":[0.2,0.8,1.5,3.4,4.8], "築年数":[30, 25, 5, 20, 50], "部屋数":[1,3,3,4,6], "家賃":[55000,83000,64000,72000, 100000], "管理費":[5000, 10000, 10000, 20000, 30000]}, ).set_index("物件No.") df
from sklearn.preprocessing import StandardScaler #標準化のためのスケーラー sc = StandardScaler() #各列にフィットさせる sc.fit(df) #スケール変換(sc.transform(df))して,データフレームに入れなおす df_sc = pd.DataFrame(sc.transform(df), index=df.index,columns=df.columns) #確認 df_sc
- 各データから最小値を引き,値域の幅で割る
from sklearn.preprocessing import MinMaxScaler #正規化のためのスケーラー sc = MinMaxScaler() #各列にフィットさせる sc.fit(df) #スケール変換(sc.transform(df))して,データフレームに入れなおす df_sc = pd.DataFrame(sc.transform(df), index=df.index,columns=df.columns) #確認 df_sc