#はじめに
pandasでデータ分析する時によく使う手法をまとめました。随時、加筆修正していきます。
#1.DataFrameの作成
#DataFrameを作成し、リストを格納
pd_sample = pd.DataFrame(リスト)
#DataFrameを作成し、辞書で複数のリストを格納
pd_sample = pd.DataFrame({"列A":リストA, "列B":リストB})
#空のDataFrameを作成し、後続処理で別のDataFrameを結合
pd_sampleA = pd.DataFrame()
pd_sampleA = pd.concat([pd_sampleA, pd_sampleB])
#列の追加
B = {a:b for a in A for b in B if x[a,b].value() == 1}
pd_sample['列B'] = pd_sample['列A'].map(B)
#2.データの結合(ユニオン)
#pandas.concat()関数
pd_sampleAll = pd.concat([pd_sampleA, pd_sampleB], ignore_index=True)
pd_sampleA
列A | 列B | 列C | |
---|---|---|---|
0 | a | b | c |
pd_sampleB
列C | 列D | |
---|---|---|
0 | y | z |
pd_sampleAll = pd.concat([pd_sampleA, pd_sampleB], ignore_index=True)
列A | 列B | 列C | 列D | |
---|---|---|---|---|
0 | a | b | c | NaN |
1 | NaN | NaN | y | z |
#3.データの結合(ジョイン)
#pandas.merge()関数
pd_sampleAll = pd.merge(pd_sampleA, pd_sampleB, on="列ラベル", how="left")
#pandas.DataFrameのmerge()メソッド
pd_sampleAll = pd_sampleA.merge(pd_sampleB, on="列ラベル", how="left")
#複数の列をキーに結合
pd_sampleAll = pd.merge(pd_sampleA, pd_sampleB, on=["列A", "列B"], how="left")
#キーの列名が異なる場合の結合
pd_sampleAll = pd.merge(pd_sampleA, pd_sampleB, left_on="列A", right_on="列AAA", how="left")
pd_sampleA
列A | 列B | 列C | |
---|---|---|---|
0 | a | b | c |
1 | aaa | bbb | ccc |
pd_sampleB
列A | 列D | |
---|---|---|
0 | a | x |
1 | aa | y |
pd_sampleAll = pd.merge(pd_sampleA, pd_sampleB, on="列A", how="left")
列A | 列B | 列C | 列D | |
---|---|---|---|---|
0 | a | b | c | x |
1 | aaa | bbb | ccc | NaN |
#4.データの抽出
#列名指定でpandas.DataFrameを抽出
pd_sampleA = pd_sampleAll[["列A", "列B"]]
#pandas.loc()関数で行ラベルと列ラベルの位置を指定して抽出
#単一行取り出す時はSeries型、複数行取り出した時はDataFrame型が返る
#行ラベルには行名のほかにboolean型を返す条件式を指定することもできる
#複数列、行をスライスすることもできる
pd_sampleA = pd_sampleAll["列ラベル"].loc["行ラベル"]
pd_sampleA = pd_sampleAll.loc["行ラベル", "列ラベル"]
pd_sampleA = pd_sampleAll.loc[pd_sampleAll["列ラベル"]!=9999]
#pandas.iloc()関数で行番号と列番号の位置を指定して抽出
#単一行取り出す時はSeries型、複数行取り出した時はDataFrame型が返る
#複数列、行をスライスすることもできる
pd_sampleA = pd_sampleAll.iloc["行番号", "列番号"]
#pandas.isin()メソッドで引数に渡したリストの要素と一致する行を抽出
pd_sampleA = pd_sampleAll["列ラベル"].isin([ "A", "B"])
pd_sampleAll
列A | 列B | 列C | 列D | |
---|---|---|---|---|
0 | a | b | c | d |
1 | aaa | bbb | ccc | ddd |
pd_sampleA = pd_sampleAll.loc[pd_sampleAll["列A"]=="aaa", ["列B", "列C"]]
列B | 列C | |
---|---|---|
1 | bbb | ccc |
#5.欠損値の確認
#pandas.Series.isnull()メソッドで欠損値の存在する行を取得
pd_sample = pd_sample["列A"].isnull()
#isnull()メソッドにany()を用いて欠損値を含む列の有無を確認
pd_sample["列A"].isnull().any(axis=0)
#isnull()メソッドにsum()を用いて欠損値を含む列の数を確認
pd_sample["列A"].isnull().sum()
#pandas.DataFrame.dropna()メソッドで特定の列が欠損している行を削除
pd_sample = pd_sample.dropna(subset=["列A"])
#pandas.DataFrame.fillna()メソッドで欠損値を任意の値に置換
pd_sample = pd_sample.fillna({"列A": "AAA", "列B": "BBB"}))
pd_sample["age"] = pd_sample["age"].fillna(pd_sample["age"].mean())
#6.日付変換
#pandas.to_datetime()関数で文字列(object型)をdatetime型に変換
import datetime
pd_sample["日付"] = pd.to_datetime(pd_sample["日付"])
#datetime型に対してdtアクセサを用いて年月日、時分秒、曜日などを取得
pd_sample["月"] = pd_sample["日付"].dt.month
#datetime型のstrftime()メソッドで日時を任意の書式の文字列に変換
pd_sample["年月"] = pd_sample["日付"].dt.strftime("%Y%m")
#datetime型のtimedeltaオブジェクトのtotal_seconds()メソッドを用いて2つの時間の差を取得
pd_sample["経過時間"] = (pd_sample["日付1"] - pd_sample["日付2"]).map(lambda x: x.total_seconds()/3600)
#applyを使った場合
#def calc_delta(t):
# t1, t2 = t
# delta = t2 - t1
# return delta.total_seconds()/3600
#pd_sample["経過時間"] = pd_sample[["日付1"], ["日付2"]].apply(calc_delta, axis=1)
#datetime型のtimedeltaオブジェクトの days()メソッドを用いて2つの日付の日数差を取得
pd_sample["経過日数"] = (pd_sample["日付1"] - pd_sample["日付2"]).map(labda x: x.days)
#dateutilモジュールのrelativedeltaオブジェクトを用いて2つの日付の月数差を取得
#戻り値に2つの日付の差が(years=+1, months=+10, days=+8)という形で格納される
from dateutil.relativedelta import relativedelta
delta = relativedelta(pd_sample["日付1"], pd_sample["日付2"])
pd_sample["経過月数"] = delta.years*12 + delta.months
#dateutilモジュールのrelativedeltaオブジェクトを用いて任意の時間差のデータを取得
pd_sample["1ヶ月前"] = pd_sample['日付'].map(lambda x: x - relativedelta(months=1))
#7.集計
#DataFrame型同士の演算
pd_ratio = (pd_sampleA / pd_sampleAll) * 100
#pandas.DataFrame.groupby()関数でまとめたい列と集計方法を指定して集計
#デフォルトではグループラベルがindexになるため、そうしたくない場合はas_index=Falseを指定する。
pd_count = pd_sample.groupby("まとめたい列").count()
pd_sum = pd_sample.groupby(["まとめたい列1", "まとめたい列2"], as_index=False).sum()[["合計したい列1", "合計したい列2"]]
#pandas.DataFrame.resample()メソッドで時系列データを集約
#引数にD(日)、W(週)などの頻度を指定し、sum()、count()、mean()などのメソッドを呼び出すことで集約した値を算出
pd_resampled = pd_sample.resample('D').sum()
#pandas.unique()関数で重複を除外したユニークなデータ件数を取得
pd_unique = pd.unique(pd_sample["列A"])
pd_unique = pd_sample["列A"].unique()
#8.その他の手法
#pandas.agg()関数で特定の列の平均値、中央値、最大値、最小値を出力
pd_sample = pd_sample.agg(["mean", "median", "max", "min"])["集計したい列"]
#pandas.DataFrame.describe()関数でデータ件数、平均値、標準偏差、最小値、四分位数、中央値、最大値を出力
#デフォルトでは数値(整数型int、浮動小数点型float)の列のみが選択される
pd_sample.describe()
#DateFrame型に対してstrアクセサを用いて文字列を操作
pd_sample["列A"] = pd_sample["列A"].str.replace(" ", "")
#pandas.DataFrameのwhere()メソッドで条件に応じて値を代入する
#Trueの場合は呼び出し元のオブジェクト、Falseの場合は第二引数が適用される
pd_sample["列A"] = pd_sample["列A"].where(pd_sample["列B"]>3, 0)
#pandas.DataFrameのmask()メソッドで条件に応じて値を代入する
#Trueの場合は第二引数、Falseの場合は呼び出し元のオブジェクトが適用される
pd_sample["列A"] = pd_sample["列A"].mask(pd_sample["列B"]>3, 0)
#DataFrame型をリスト型に変換
pd_sample_columns = pd_sample.columns.tolist()
#pivotをmeltする
pd_sample_vertical = pd_sample.melt(id_vars=['列A'], value_vars=['列B', '列C', '列D'], var_name='列BCD', value_name='列BCD値')