7
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【初心者向け】はじめてのpythonデータハンドリング

Last updated at Posted at 2019-09-11

##1.はじめに

  • 筆者はSPSS ModelerやSQLを用いて集計をする機会が多く、pythonでデータ集計をする際に関数を忘れてしまうのでよく使うコードを整理しました。
  • ライブラリは、データ加工はpandas、グラフはseabornをメインで利用しています。
  • 関数だけ記述してもわかりにくいため、今回はseabornにあるtitanicデータを拝借しています。
  • 筆者はjupyter notebook上で処理しています。
  • 各処理を理解することに重点を置いているため、集計内容に深い意味はありません。
  • SPSS Modeler、SQLとの対応についても簡単に記述しています。

※ただし完全に同じではないので、あくまで処理イメージとしてください。
※SQLはRDBMSの種類によって書き方が異なる箇所がありますのでご留意ください。

##2.事前準備

##3.ライブラリと利用データのインポート
今回利用するライブラリとデータをロードします。

実行コード
#pandasを宣言
import pandas as pd

#numpyを宣言
import numpy as np

#matplotlibを宣言
from matplotlib import pyplot as plt

#jupyter notebook上で表示
%matplotlib inline

#seabornを宣言
import seaborn as sns

# seabornのtitanicデータをインポート
rawdata = sns.load_dataset('titanic')

##4.データの読み込み・書き出し
今回はseabornから読み込んでいるデータを利用するが、csvファイルから読み込みを行うことが多いため記述しています。

今回は使わない
#読み込み
#(参考)headerがない場合は、引数にheader=Noneを入れる
train = pd.read_csv("train.csv" , encoding='shift_jis')

#書き出し
rawdata.to_csv("rawdata.csv" , index = None , header = None)

##5.データの確認
まれにカラムずれなど明らかにおかしなデータセットとなっている場合があるので、データの大きさや中身について、最低限の確認を行います。

SPSS modeler:サンプルノード
SQL:LIMIT句

実行コード
#先頭行の確認
rawdata.head()

スクリーンショット 2019-09-10 16.36.18.png

実行コード
#後尾行の確認
#関数の場合、()の中にオプションを入れられる。今回は10行を見る。デフォルトは5行
rawdata.tail(10)

スクリーンショット 2019-09-10 16.44.41.png

実行コード
#行数、列数の確認
rawdata.shape

(891, 15)

実行コード
#重複を削除した配列作成
np.unique(rawdata["embark_town"])

スクリーンショット 2019-09-30 13.20.17.png

##6.データ型
データ型の確認と、意図と異なっていた場合は変更します。
特に、数値データは(定量的に)数字として扱うのか、コード値として扱うのか確認します。

SPSS modeler:データ型ノード
SQL:CAST関数など

実行コード

#データ型の確認
rawdata.info()

スクリーンショット 2019-09-10 16.46.01.png

実行コード
#データ型変換
#(例)文字列型に変換
rawdata["pclass"] = rawdata["pclass"].astype(np.str)
rawdata.info()

スクリーンショット 2019-09-10 16.48.28.png

実行コード
#データ型変換
#(例)数値列型に変換
rawdata["pclass"] = rawdata["pclass"].astype(np.int)
rawdata.info()

スクリーンショット 2019-09-10 16.50.32.png

##7.統計量の確認
ざっくりとした各カラムの全体傾向の確認します。

実行コード
#要約統計量の確認 
rawdata.describe()

スクリーンショット 2019-09-10 16.51.34.png

実行コード

#平均値の確認 
rawdata.mean()

スクリーンショット 2019-09-10 16.52.29.png

実行コード

#一部カラムの平均値の確認
rawdata["age"].mean()

29.69911764705882

実行コード
#相関係数の確認
rawdata[["pclass","survived"]].corr()

スクリーンショット 2019-09-10 16.53.49.png

##8.欠損値処理
利用するデータによっては、欠損値が存在します。存在する場合は集計前に対応しておきます。

実行コード
# 欠損値のあるカラムを確認(いずれかのカラムに欠損値があるとTrue)
rawdata.isnull().any()

スクリーンショット 2019-09-10 16.54.29.png

実行コード

# 各カラムの欠損値の数を確認
rawdata.isnull().sum()

スクリーンショット 2019-09-10 16.54.55.png

実行コード

# 欠損値を平均値で補完
rawdata["age"] = rawdata["age"].fillna(rawdata["age"].mean())
# 欠損値があるレコードは削除
rawdata = rawdata.dropna(subset=["embarked"])

##9.基礎集計
1変数のデータ傾向や、変数間のデータ傾向を定量的に確認します。

実行コード
# 1変数集計 レコードカウント
rawdata["sex"].value_counts()

スクリーンショット 2019-09-10 16.56.25.png

実行コード

# 2変数(クロス)集計 レコードカウント margins=Trueとして、総和も表示
pd.crosstab(rawdata["sex"] , rawdata["survived"] , margins=True)

スクリーンショット 2019-09-10 16.58.20.png

実行コード
# 2変数(クロス)集計 行和が100%
cross_tab = pd.crosstab(rawdata["sex"] , rawdata["survived"])
cross_tab.apply(lambda x:x/sum(x),axis=1)

スクリーンショット 2019-09-10 16.59.10.png

##10.レコード抽出
集計に用いるレコードのみを抽出します。

SPSS modeler:条件抽出ノード
SQL:WHERE句

実行コード
#抽出条件が数値データ
#(例)ageが30以上のレコードを抽出
rawdata[rawdata["age"] >= 30]

スクリーンショット 2019-09-10 17.01.03.png

実行コード

#抽出条件が文字列(完全一致)
#(例)sexがfemaleのレコードを抽出
rawdata[rawdata["sex"] == "female"]

スクリーンショット 2019-09-10 17.03.11.png

実行コード
#抽出条件が文字列(完全一致)
#(例)最初の2文字を抽出
rawdata["class"].str[:2]

スクリーンショット 2019-09-30 13.56.29.png

実行コード
#抽出条件が文字列(完全一致)
#(例)3文字目以降を抽出
rawdata["class"].str[2:]

スクリーンショット 2019-09-30 13.57.01.png

実行コード
#抽出条件が文字列の場合(部分一致)
#(例)sexに「fe」を含むレコードを抽出
rawdata[rawdata["sex"].str.contains('fe')]

スクリーンショット 2019-09-10 17.04.08.png

実行コード
#抽出条件が文字列の場合(前方部分一致)
#(例)classの最後の文字に「Fir」を含むレコードを抽出
rawdata[rawdata["class"].str.startswith('Fir')]

スクリーンショット 2019-09-10 17.05.05.png

実行コード
#抽出条件が文字列の場合(後方部分一致)
#(例)classの最後の文字に「st」を含むレコードを抽出
rawdata[rawdata["class"].str.endswith('st')]

スクリーンショット 2019-09-10 17.06.06.png

実行コード
#抽出条件がorで複数ある場合
#(例)ageが30以上 もしくは sexがfemaleのレコードを抽出
rawdata[(rawdata["sex"] == "female" ) | (rawdata["age"] >= 30)]

スクリーンショット 2019-09-10 17.06.47.png

実行コード
#抽出条件がandで複数ある場合
#(例)ageが30以上 かつ sexがfemaleのレコードを抽出
rawdata[(rawdata["sex"] == "female" ) & (rawdata["age"] >= 30)]

スクリーンショット 2019-09-10 17.07.14.png

##11.カラム抽出
集計に用いるカラムのみを抽出します。

SPSS modeler:フィルターノード、カラム順序入替ノード
SQL:SELECT句

実行コード
#必要なカラムのみ抽出(1カラムの場合)
#(例)survivedのみ抽出
rawdata["survived"]

スクリーンショット 2019-09-10 17.08.40.png

実行コード
#必要カラム名のみ抽出(複数カラムの場合)
#(例)survivedとsexを抽出
rawdata[["survived","sex"]]

スクリーンショット 2019-09-10 17.09.20.png

実行コード
#カラム名を変更する
#(例)who を sex_child に変換
rawdata.rename(columns={'who': 'sex_child'}, inplace=True)
rawdata.head()

スクリーンショット 2019-09-10 17.10.11.png

##12.レコード&カラム抽出
集計に用いるレコードとカラムのみを抽出します。

  • loc

行、列をラベルで指定

  • iloc

行、列を番号で指定

実行コード
#カラム名から抽出(全レコード)
#(例)カラム「survived」と「sex」を抽出
rawdata.loc[:,["survived","sex"]]

スクリーンショット 2019-09-10 17.10.59.png

実行コード
#カラム番号から抽出(全レコード)
#(例)0番目、1番目、2番目、3番目、6番目、12番目のカラムを抽出
rawdata.iloc[:,[0,1,2,3,6,12]]

スクリーンショット 2019-09-10 17.11.41.png

実行コード
#レコード番号、カラム番号から抽出
#(例)2行目、3行目のレコードかつ、0番目、1番目のカラムを抽出
rawdata.iloc[[2,3], [0,1]]

スクリーンショット 2019-09-10 17.12.06.png

##13.置換
データの中身を置換します。

SPSSmodeler:置換ノード
SQL:replace関数

実行コード
#文字列の置換
#(例)「embark_town」カラムにある「Southampton」を「England」に置換する
rawdata["embark_town"].replace("Southampton" , "England")

スクリーンショット 2019-09-10 17.13.33.png

##14.新カラム作成
既存のデータを用いて新たなデータを作成します。

SPSS modeler:フィールド作成ノード

実行コード
#1変数を用いて新カラム作成
#(例)ageが20未満の場合、childが1、それ以外(欠損値なども含む)を0とする
rawdata["child"] = rawdata["age"].apply(lambda x : 1  if x < 20 else 0)
rawdata.head(10)

スクリーンショット 2019-09-10 17.24.13.png

実行コード

# 1変数を用いて新カラム作成
#(例)embark_townがCherbourgの場合はFrance、Queenstownの場合はNew Zealand、Southamptonの場合はEnglandとして新カラムembark_town_renameを作成
rawdata["embark_town_rename"] = rawdata["embark_town"].map({"Cherbourg":"France", "Queenstown":"New Zealand" , "Southampton":"England" }) 
rawdata.head(6)

スクリーンショット 2019-09-10 17.15.33.png

実行コード
#2変数以上を用いて新カラム作成(複雑な条件の場合)
#(例)今回は、テレビ広告で用いられることの多いターゲット区分を用いる。
#まずは、ageとsexから定義表を作成
def target_class(sex,age):
    if  age >= 4 and age <= 12:
        return "C"
    elif age >= 13 and age <= 19:
        return "T"
    elif sex == "male" and age >= 20 and age <= 34:
        return "M1"
    elif sex == "male" and age >= 35 and age <= 49:
        return "M2"
    elif sex == "male" and age >= 50:
        return "M3"
    elif sex == "female" and age >= 20 and age <= 34:
        return "F1"
    elif sex == "female" and age >= 35 and age <= 49:
        return "F2"
    elif sex == "female" and age >= 50:
        return "F3"
    else:
        return "OTHER"

#定義表にあてはまる形で新カラムtarget_classを作成
rawdata["target_class"] = rawdata.apply(lambda rawdata: target_class(rawdata["sex"], rawdata["age"]), axis=1)
rawdata.head()

スクリーンショット 2019-09-10 17.25.20.png

実行コード

#数値データから閾値を設けて新カラム作成
#(例)ageを10刻みに分ける
rawdata["age_bining"] = pd.cut(rawdata["age"],[0,20,30,40,50,60,100])
rawdata.head()

スクリーンショット 2019-09-10 17.26.12.png

実行コード
#ダミー変数として作成
pd.get_dummies(rawdata[["sex","embark_town"]])

スクリーンショット 2019-09-11 10.38.23.png

実行コード
#小数点0桁を表示
round(rawdata["fare"],0)

スクリーンショット 2019-09-30 14.02.45.png

##15.レコード集計
グループごとに集計を行います。

SPSS modeler:レコード集計ノード
SQL:GROUP BY句

実行コード
#レコード集計後、レコード件数を表示
#(例)pclass×sexのレコード件数
rawdata.groupby(["pclass" , "sex"], as_index=False).size()

スクリーンショット 2019-09-11 10.39.33.png

実行コード
#集計結果を再度テーブル化する
rawdata.groupby(["pclass" , "sex"]).size().reset_index()

スクリーンショット 2019-09-30 13.29.16.png

実行コード
#レコード集計後、平均値を表示(全ての数値カラム)
#(例)pclass×sexの平均値
rawdata.groupby(["pclass" , "sex"], as_index=False).mean()

スクリーンショット 2019-09-11 10.40.33.png

実行コード
#レコード集計後、平均値を表示(一部の数値カラム)
#(例)pclass×sexのage平均値
rawdata.groupby(["pclass" , "sex"], as_index=False)["age"].mean()

スクリーンショット 2019-09-11 10.41.26.png

##16.ピボットテーブル
行、列、集計値を指定して、自由自在に集計を行います。
SPSS modeler:再構成ノード、レコード集計ノード

pd.pivot_table(data, values=[値のカラム名], index=[行のカラム名], columns=[列のカラム名], aggfunc='[集計を行う関数]',margins=[True/False])

実行コード
#集計値を平均値としたピボットテーブル
#(例)行をsex、列をpclassとしたピボットテーブル
pd.pivot_table(rawdata, index="sex", columns="pclass", values="age",margins=True)

スクリーンショット 2019-09-11 10.54.47.png

実行コード
#集計値を最小値、最大値としたピボットテーブル
#(例)行をsex、列をpclassとしたピボットテーブル
pd.pivot_table(rawdata, index="sex", columns="pclass", values="age", aggfunc=[min, max],margins=True)

スクリーンショット 2019-09-11 10.55.18.png

実行コード
#先ほどの結果を行へピボット
pd.pivot_table(rawdata, index="sex", columns="pclass", values="age", aggfunc=[min, max],margins=True).stack()
  • stack 列から行へのピボット
  • unstack 行から列へのピボット

スクリーンショット 2019-09-30 13.35.45.png

##17.レコード結合
2つ以上のデータセットの結合を行います。(横に繋げる)

SPSS modeler:レコード結合ノード
SQL:JOIN句

実行コード
#(例)事例で用いる結合マスタを作成
sex_class_master = pd.DataFrame([["male", "First","male_first"],
                                   ["male", "Second","male_second"],
                                   ["male", "Third","male_third"],
                                   ["female", "First","female_first"],
                                   ["female", "Second","female_second"],
                                   ["female", "Third","female_third"]],
                                   columns=["sex", "class","sex_class"])
sex_class_master

スクリーンショット 2019-09-11 10.56.00.png

実行コード
#内部結合
#(例)rawdataと先ほど作成したsex_class_masterのデータセットから、sexとclassをキーとして結合
pd.merge(rawdata, sex_class_master,  on=["sex","class"])

スクリーンショット 2019-09-11 10.56.41.png

実行コード
#左部分外部結合
#(例)rawdataと先ほど作成したsex_class_masterのデータセットから、sexとclassをキーとして結合
pd.merge(rawdata, sex_class_master, how="left", on=["sex","class"])

スクリーンショット 2019-09-11 10.58.32.png

##18.レコード追加
2つ以上のデータセットの結合を行います。(縦に繋げる)

SPSS modeler:レコード追加ノード
SQL:UNION句

実行コード
#(例)事例用にデータ分割
rawdata_male = rawdata[rawdata["sex"] == "male"]
rawdata_female = rawdata[rawdata["sex"] == "female"]

#レコード追加
#列名を同じにする必要がある。また、indexを振り直す場合、ignore_index=Trueとする 
#(例)先ほど作成したrawdata_maleとrawdata_femaleを縦に積む
rawdata = pd.concat([rawdata_male,rawdata_female], ignore_index=True)

##19.行列入れ替え
SPSS modeler:行列入れ替えノード

実行コード
#(例)事例用に行をsex、列をpclassとしたピボットテーブルを作成
sc_temp = pd.pivot_table(rawdata, index="sex", columns="class", values="age",margins=True)
sc_temp

スクリーンショット 2019-09-11 11.00.17.png

実行コード
#行列を入れ替え
#(例)先ほど作成した、sc_tempを用いて行列入れ替え
sc_temp.T

スクリーンショット 2019-09-11 11.00.31.png

##20.並べ替え
SPSS modeler:並べ替えノード
SQL:ORDER BY句

実行コード
#昇順
#(例)ageで昇順
rawdata.sort_values(by="age")

スクリーンショット 2019-09-11 11.02.10.png

実行コード
#降順
#(例)ageで降順
rawdata.sort_values(by="age", ascending=False)

スクリーンショット 2019-09-11 11.02.51.png

##21.グラフ基本
データの傾向を視覚的に確認します。

SPSS modeler:各グラフノード

実行コード
#ヒストグラム
#(例)ageの分布を10刻みとして確認
sns.distplot(rawdata["age"],kde=False, bins=10)

スクリーンショット 2019-09-11 11.07.14.png

実行コード
#箱ひげ図
#(例)sexごとにageのばらつきを確認
sns.boxplot(x="sex", y="age", data=rawdata )

スクリーンショット 2019-09-11 11.08.13.png

実行コード
# 散布図
#(例)ageとfareの関係性を確認
sns.scatterplot(x="age", y="fare", data=rawdata)

スクリーンショット 2019-09-11 11.08.40.png

実行コード
# 散布図(ヒストグラムも同時に表示)
#(例)ageとfareの関係性を確認
sns.jointplot(x="age", y="fare", data=rawdata)

スクリーンショット 2019-09-11 11.09.10.png

実行コード
# 棒グラフ(縦軸:レコードカウント)
#(例)sex別pclassのレコードカウント
sns.countplot(x="sex", hue="pclass",  data=rawdata)

スクリーンショット 2019-09-11 11.09.29.png

実行コード
# 棒グラフ(データの平均値と信頼区間を出力)
#(例)sex別pclassのsurvivedの平均値
sns.barplot(x="sex", y="survived", hue="pclass", data=rawdata)

スクリーンショット 2019-09-11 11.09.47.png

実行コード
#積み上げ棒グラフ
#(例)事例用に、sexとsurvivedのクロス表を作成
cross_tab_temp = pd.crosstab(rawdata["sex"] , rawdata["survived"] )
cross_tab_temp

スクリーンショット 2019-09-11 11.10.34.png

実行コード
#(例)sex別のsurvivedごとのレコードカウント
cross_tab_temp.plot.bar(stacked=True)

スクリーンショット 2019-09-11 11.11.09.png

実行コード
#折れ線グラフ
#(例)事例用にage×sexのfareの平均値のデータセットを作成
temp = pd.DataFrame(rawdata.groupby(["age" , "sex"], as_index=False)["fare"].mean())
temp

スクリーンショット 2019-09-11 11.15.47.png

実行コード
#(例)sex別age×fareの折れ線グラフ
sns.lineplot(x="age", y="fare", hue="sex", data=temp)

スクリーンショット 2019-09-11 11.16.08.png

実行コード
#帯グラフ
#(例)事例用にclassとtarget_classのクロス表(行和100%)を作成
cross_tab = pd.crosstab(rawdata["class"] , rawdata["target_class"] )
cross_tab_rate = cross_tab.apply(lambda x:x/sum(x),axis=1)
cross_tab_rate

スクリーンショット 2019-09-11 11.17.15.png

実行コード
#(例)classごとのtarget_classの帯グラフ
#1回で作成出来ないため、target_classの項目別の積み上げ棒グラフを繰り返しで作成するイメージ
temp = []
ncol = len(cross_tab_rate.columns)
for i in range(ncol):
    if i == 0:
        plt.bar(cross_tab_rate.index,cross_tab_rate.iloc[:,i],label=cross_tab_rate.columns[i])
        temp = cross_tab_rate.iloc[:,i]
    else:
        plt.bar(cross_tab_rate.index,cross_tab_rate.iloc[:,i], bottom=temp,label=cross_tab_rate.columns[i])
        temp = temp + cross_tab_rate.iloc[:,i]
plt.legend( bbox_to_anchor=(0.8, 0.3, 0.5, 0.5))

スクリーンショット 2019-09-11 11.17.56.png

##22.グラフオプション
グラフのカスタマイズを行います。以下にも詳しく記述されています。

Python: seaborn を使った可視化を試してみる
seabornでMatplotlibの見た目を良くする

実行コード
#背景を変更
#(例)whitegridにする
sns.set_style("whitegrid")
sns.distplot(rawdata["age"],kde=False, bins=10)

スクリーンショット 2019-09-11 11.22.19.png

実行コード
#カラーパレットを変更
#(例)Pastel1にする
sns.countplot(x="sex", hue="pclass",  data=rawdata, palette="Pastel1")

スクリーンショット 2019-09-11 11.34.16.png

実行コード
#タイトル作成
#(例)sex × pclass countとする
sns.countplot(x="sex", hue="pclass",  data=rawdata)
plt.title("sex × pclass count")

スクリーンショット 2019-09-11 11.35.41.png

実行コード
#グラフを保存
sns.countplot(x="sex", hue="pclass",  data=rawdata)
plt.title("sex × pclass count")
plt.savefig("sex × pclass count.png")
実行コード
#グラフを横にして作成
sns.boxplot(x="age", y="sex", orient="h" , data=rawdata )

スクリーンショット 2019-09-30 13.45.24.png

実行コード
#グラフのサイズ変更
plt.figure(figsize=(20, 5))
sns.distplot(rawdata["age"],kde=False)

スクリーンショット 2019-09-30 13.47.41.png

##23.参考リンク
データ分析で頻出のPandas基本操作
[Python] pandasの使い方まとめ
Python でデータサイエンス

7
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?