tropicbirdのブログ

備忘録です。

【学習記録】Python データサイエンスハンドブック(45)

オライリーの「Pythonデータサイエンスハンドブック」の学習記録

3.12.7 事例:シアトル市の自動車数を可視化する。
#ファイル名を指定してcurlで保存する場合は「-o」を使う。備忘録参照。
In [69]: !curl -o FremontBridge.csv https://data.seattle.gov/api/views/65db-xm6k/ro
    ...: ws.csv?accessType=DOWNLOAD
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1679k    0 1679k    0     0   347k      0 --:--:--  0:00:04 --:--:--  378k

In [71]: data=pd.read_csv('FremontBridge.csv')
In [79]: data.columns
Out[79]: Index(['Date', 'Fremont Bridge East Sidewalk', 'Fremont Bridge West Sidewalk'], dtype='object')

#Dateをdataのインデクスに指定する。
In [81]: data=data.set_index('Date')

In [82]: data.head()
Out[82]:
                        Fremont Bridge East Sidewalk  \
Date
01/01/2019 12:00:00 AM                           0.0
01/01/2019 01:00:00 AM                           2.0
01/01/2019 02:00:00 AM                           1.0
01/01/2019 03:00:00 AM                           1.0
01/01/2019 04:00:00 AM                           2.0

                        Fremont Bridge West Sidewalk
Date
01/01/2019 12:00:00 AM                           9.0
01/01/2019 01:00:00 AM                          22.0
01/01/2019 02:00:00 AM                          11.0
01/01/2019 03:00:00 AM                           2.0
01/01/2019 04:00:00 AM                           1.0

#列名を短くする。
In [83]: data.columns=['West','East']

#WestとEastの合計の列(TOtal)を追加する。
In [84]: data['Total']=data.eval('West+East')

In [85]: data.head()
Out[85]:
                        West  East  Total
Date
01/01/2019 12:00:00 AM   0.0   9.0    9.0
01/01/2019 01:00:00 AM   2.0  22.0   24.0
01/01/2019 02:00:00 AM   1.0  11.0   12.0
01/01/2019 03:00:00 AM   1.0   2.0    3.0
01/01/2019 04:00:00 AM   2.0   1.0    3.0

#dataの要約統計を見てみる。
In [86]: data.dropna().describe()
Out[86]:
               West          East         Total
count  59823.000000  59823.000000  59823.000000
mean      52.619795     60.262324    112.882119
std       67.734326     87.871363    143.101423
min        0.000000      0.000000      0.000000
25%        6.500000      7.000000     15.000000
50%       29.000000     30.000000     61.000000
75%       70.000000     73.000000    147.000000
max      698.000000    850.000000   1097.000000
3.12.7.1 データの可視化を行う。
#単純にプロットしてみる。
#インデクスが見た目は時系列だけど、dypeはobjectになっているので、思ったようなグラフにならない。
In [87]: %matplotlib
Using matplotlib backend: TkAgg

In [88]: import seaborn; seaborn.set()

In [89]: data.plot()
Out[89]: <matplotlib.axes._subplots.AxesSubplot at 0x7f7e7aa4bfd0>

In [90]: plt.ylabel('Hourly Bicycle Count')
Out[90]: Text(27.625, 0.5, 'Hourly Bicycle Count')

In [93]: data.index
Out[93]:
Index(['01/01/2019 12:00:00 AM', '01/01/2019 01:00:00 AM',
       '01/01/2019 02:00:00 AM', '01/01/2019 03:00:00 AM',
       '01/01/2019 04:00:00 AM', '01/01/2019 05:00:00 AM',
       '01/01/2019 06:00:00 AM', '01/01/2019 07:00:00 AM',
       '01/01/2019 08:00:00 AM', '01/01/2019 09:00:00 AM',
       ...
       '12/06/2016 12:00:00 AM', '01/22/2016 08:00:00 PM',
       '04/04/2017 01:00:00 AM', '01/18/2013 04:00:00 AM',
       '01/12/2017 04:00:00 AM', '02/29/2016 12:00:00 AM',
       '09/13/2013 03:00:00 AM', '12/07/2016 12:00:00 AM',
       '03/29/2013 04:00:00 AM', '05/24/2017 01:00:00 AM'],
      dtype='object', name='Date', length=59832)

f:id:tropicbird:20190812171655p:plain

#インデクスの dtypeをdatetime64に変換してからプロットする。
#思い通りのグラフができる。
In [95]: data.index=pd.DatetimeIndex(data.index)

In [96]: data.index
Out[96]:
DatetimeIndex(['2019-01-01 00:00:00', '2019-01-01 01:00:00',
               '2019-01-01 02:00:00', '2019-01-01 03:00:00',
               '2019-01-01 04:00:00', '2019-01-01 05:00:00',
               '2019-01-01 06:00:00', '2019-01-01 07:00:00',
               '2019-01-01 08:00:00', '2019-01-01 09:00:00',
               ...
               '2016-12-06 00:00:00', '2016-01-22 20:00:00',
               '2017-04-04 01:00:00', '2013-01-18 04:00:00',
               '2017-01-12 04:00:00', '2016-02-29 00:00:00',
               '2013-09-13 03:00:00', '2016-12-07 00:00:00',
               '2013-03-29 04:00:00', '2017-05-24 01:00:00'],
              dtype='datetime64[ns]', name='Date', length=59832, freq=None)

In [97]: data.plot()
Out[97]: <matplotlib.axes._subplots.AxesSubplot at 0x7f7e593aaa20>

In [98]: plt.ylabel('Hourly Bicycle Count')
Out[98]: Text(22.375, 0.5, 'Hourly Bicycle Count')

f:id:tropicbird:20190812171715p:plain

#毎時データではギザギザなので、毎週データに再サンプリングする。
In [99]: weekly=data.resample('W').sum()

In [100]: weekly.plot(style=[':','--','-'])
Out[100]: <matplotlib.axes._subplots.AxesSubplot at 0x7f7e4c597b38>

In [101]: plt.ylabel('Weekly bicycle count')
Out[101]: Text(12.500000000000002, 0.5, 'Weekly bicycle count')

In [102]: weekly.head()
Out[102]:
              West    East    Total
Date
2012-10-07  7297.0  6995.0  14292.0
2012-10-14  8679.0  8116.0  16795.0
2012-10-21  7946.0  7563.0  15509.0
2012-10-28  6901.0  6536.0  13437.0
2012-11-04  6408.0  5786.0  12194.0

f:id:tropicbird:20190812171745p:plain

#30日間の移動平均を行い、1日当たりの平均を求める
#30日間の合計のグラフを作成する。

In [103]: daily=data.resample('D').sum()

In [104]: daily.head()
Out[104]:
              West    East   Total
Date
2012-10-03  1760.0  1761.0  3521.0
2012-10-04  1708.0  1767.0  3475.0
2012-10-05  1558.0  1590.0  3148.0
2012-10-06  1080.0   926.0  2006.0
2012-10-07  1191.0   951.0  2142.0

In [105]: daily.rolling(30,center=True).sum().plot(style=[':','--','-'])
Out[105]: <matplotlib.axes._subplots.AxesSubplot at 0x7f7e4c4c2828>

In [106]: daily.rolling(30,center=True).sum().plot(style=[':','--','-'])
Out[106]: <matplotlib.axes._subplots.AxesSubplot at 0x7f7e7acbbf60>

In [107]: plt.ylabel('mean hourly count') #これはたぶん図書の誤植で、mean every 30 days countが正しい。
Out[107]: Text(2.8750000000000018, 0.5, 'mean hourly count')

f:id:tropicbird:20190812171803p:plain

#窓関数をガウス窓にすると、滑らかな移動平均を求めることが可能。
#↓のコードでは、ウィンドウの幅(50日)とウインドウ内のガウスの幅(10日)の両方を指定している(←要学習。)
In [108]: daily.rolling(50,center=True, win_type='gaussian').sum(std=10).plot(style
     ...: =[':','--','-'])
Out[108]: <matplotlib.axes._subplots.AxesSubplot at 0x7f7e4c1f4898>

f:id:tropicbird:20190812171830p:plain

【備忘録】Bash on Windowsのルートディレクトリの場所とhomeの場所

ルートディレクトリの場所

C:\Users\%WindowsUSERNAME%\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs

bashのhomeとユーザーの場所

C:\Users\%WindowsUSERNAME%\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\home\%LinuxUSERNAME%

メモ:Bash on Windows上でAnaconda3をインストールしてIPythonを使用している場合、Anaconda3のデータは↑のbash上のhome\%LinuxUSERNAME%にある。

参考にしたサイト
WSL(旧:Bash on Windows)のルートディレクトリが無い - しらとりのブログ

How to Access Your Ubuntu Bash Files in Windows (and Your Windows System Drive in Bash)

【備忘録】Python(2) lambdaの使い方

lambdaの使い方。

引用したサイト
【Python入門】lambda(ラムダ式)の使い方 | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト

#lambda式の形式
lambda 引数:処理内容

#税込み価格を求めるlambda式
prices = [3000,2500,10500,4300]
paymentList = list(map(lambda price:price * 1.08 , prices))

print(paymentList)

#if文処理のlambda式
prices = [3000,2500,10500,4300]
priceList = list(filter(lambda price:price > 3500, prices))
priceList.sort()

print(priceList)

【kaggle】タイタニックのコンペ(5)

Kaggleで定番のタイタニック号の生存者の分析をPythonで行う記録。

↓コンペのサイトはここです。
Titanic: Machine Learning from Disaster | Kaggle

Pythonによる分析の一例をManav Sehgalさんのカーネルを参考に(と言いうかこれに沿って)行います。
↓Manav Sehgalさんの分析手順はここで確認ができます。
Titanic Data Science Solutions | Kaggle

17.データラングリング

・今までの分析の結果、様々な予想を立てることができた。
・データはいじらずに分析をしてきたが、ここではデータ自体をいじる。

17.1.不要な属性を取り除く

・部屋番号(Cabin)とチケット(Ticket)はそこまで重要じゃなさそう。
・データラングリングするときは、トレーニングデータセットとテストデータセットの両方に対して同じ操作を行う。

In [18]: train_df.shape
Out[18]: (891, 12)

In [20]: test_df.shape
Out[20]: (418, 11)

In [22]: train_df=train_df.drop(['Ticket','Cabin'],axis=1)
In [23]: train_df.shape
Out[23]: (891, 10)

In [24]: test_df=test_df.drop(['Ticket','Cabin'],axis=1)
In [25]: test_df.shape
Out[25]: (418, 9)

In [27]: combine[1].shape
Out[27]: (418, 11)

In [28]: combine=[train_df, test_df]
In [29]: combine[1].shape
Out[29]: (418, 9)
17.2.新しい属性を既存のデータから抽出、作成する。

・名前の肩書と生存率の相関を調べたい。
・The RegEx pattern (\w+\.)を使って肩書を抽出する。

In [32]: for dataset in combine:
    ...:     dataset['Title']=dataset.Name.str.extract('([A-Za-z]+)\.',expand=False)
    ...: pd.crosstab(train_df['Title'],train_df['Sex'])
Out[32]:
Sex       female  male
Title
Capt           0     1
Col            0     2
Countess       1     0
Don            0     1
Dr             1     6
Jonkheer       0     1
Lady           1     0
Major          0     2
Master         0    40
Miss         182     0
Mlle           2     0
Mme            1     0
Mr             0   517
Mrs          125     0
Ms             1     0
Rev            0     6
Sir            0     1

In [33]: for dataset in combine:
    ...:     dataset['Title']=dataset.Name.str.extract('([A-Za-z]+)\.',expand=False)

In [42]: for dataset in combine:
    ...:     dataset['Title']=dataset['Title'].replace(['Lady','Countess','Capt',\
    ...:     'Col','Don','Dr','Major','Rev','Sir','Jonkheer','Dona'],'Rare')
    ...:     dataset['Title']=dataset['Title'].replace('Mlle','Miss')
    ...:     dataset['Title']=dataset['Title'].replace('Ms','Miss')
    ...:     dataset['Title']=dataset['Title'].replace('Mme','Mrs')

In [43]: train_df[['Title','Survived']].groupby(['Title'],as_index=False).mean()
Out[43]:
    Title  Survived
0  Master  0.575000
1    Miss  0.702703
2      Mr  0.156673
3     Mrs  0.793651
4    Rare  0.347826

In [44]: title_mapping={'Mr':1,'Miss':2,'Mrs':3,'Master':4,'Rare':5}

In [45]: for dataset in combine:
    ...:     dataset['Title']=dataset['Title'].map(title_mapping)
    ...:     dataset['Title']=dataset['Title'].fillna(0)
    ...:

In [46]: train_df.head()
Out[46]:
   PassengerId  Survived  Pclass  \
0            1         0       3
1            2         1       1
2            3         1       3
3            4         1       1
4            5         0       3

                                                Name     Sex   Age  SibSp  \
0                            Braund, Mr. Owen Harris    male  22.0      1
1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  38.0      1
2                             Heikkinen, Miss. Laina  female  26.0      0
3       Futrelle, Mrs. Jacques Heath (Lily May Peel)  female  35.0      1
4                           Allen, Mr. William Henry    male  35.0      0

   Parch     Fare Embarked  Title
0      0   7.2500        S      1
1      0  71.2833        C      3
2      0   7.9250        S      2
3      0  53.1000        S      3
4      0   8.0500        S      1

#敬称を抽出したので、名前は不要になった。なので、取り除く。
#トレーニングデータからID番号も不要なので取り除く。
#テストデータでは最後の予測にIDと紐づけるためそのままにしておく。
In [47]: train_df=train_df.drop(['Name','PassengerId'],axis=1)

In [48]: test_df=test_df.drop(['Name'],axis=1)

In [49]: combine=[train_df,test_df]

In [50]: train_df.shape, test_df.shape
Out[50]: ((891, 9), (418, 9))
17.3.定性型属性を数字に変換する。

・文字列データを数字データに変換する。多くの予測モデルのアルゴリズムでは数字データにしておく必要がある。
・性別を男性0、女性1に変換する。

In [52]: for dataset in combine:
    ...:     dataset['Sex']=dataset['Sex'].map({'female':1,'male':0}).astype(int)

In [53]: train_df.head()
Out[53]:
   Survived  Pclass  Sex   Age  SibSp  Parch     Fare Embarked  Title
0         0       3    0  22.0      1      0   7.2500        S      1
1         1       1    1  38.0      1      0  71.2833        C      3
2         1       3    1  26.0      0      0   7.9250        S      2
3         1       1    1  35.0      1      0  53.1000        S      3
4         0       3    0  35.0      0      0   8.0500        S      1

【kaggle】タイタニックのコンペ(4)

Kaggleで定番のタイタニック号の生存者の分析をPythonで行う記録。

↓コンペのサイトはここです。
Titanic: Machine Learning from Disaster | Kaggle

Pythonによる分析の一例をManav Sehgalさんのカーネルを参考に(と言いうかこれに沿って)行います。
↓Manav Sehgalさんの分析手順はここで確認ができます。
Titanic Data Science Solutions | Kaggle

14.今までの分析結果から、生存の有無について予測する。
14.1.相関(Correlating)

・予測したいことは各乗客の生存の有無である。よって、各属性データと生存の有無の相関を早い段階で確認する。

14.2.補完(Completing)

・生存の有無を予測する際に、年齢が重要な属性の場合、その欠損値を埋める必要があるかもしれない。
・乗船港も生存の有無や他の要素と相関がある可能性がるため、欠損値を埋める必要があるかもしれない。

14.3.補正(Correcting)

・チケットの属性はデータセットから取り除いてもよいかもしれない。22%のチケットに同じ名称であり、チケットの名称は生存の有無に関係ないかもしれないから。
・客室の情報も取り除いてもよかもしれない。客室の情報の多くは、トレーニングデータセットとテストデータセットにおいて、未完またはNull値であるため、
・乗客のID番号も取り除いてもよいかもしれない。ID番号は生存の有無とは関係が関係ない可能性があるため。
・乗客の名前のデータも取り除いてもよいかもしれない。全員が違う名前であり、標準化されていないため。

14.4.作成(Creating)

・ParchとSibSbデータを元に、家族(Family)のデータを作りたい可能性がある。
・名前のデータから、肩書(Mr.など)を抽出したいかもしれない。
・年齢をカテゴリー化したデータを作りたいかもしれない。つまり、定量データを順序尺度の定性データに変更したい。
・料金をカテゴリー化したデータを作りたいかもしれない。つまり、定量データを順序尺度の定性データに変更したい。

14.5.分類(Classifying)

・問題の背景や条件から、予測をすることもできる。
・女性は男性よりも生存率が高い。
・何歳以下の子どもは生存率が高い。
・等級が高い乗客(Pclass=1)は生存率が高い。

15.属性をピボットして分析する。

・今までの観測と推測を確かめるために、属性同士をピボットして簡単に分析することができる。
・この時点では、Null値がないデータのみを扱う。
・この時点では、名義尺度(性別)、順序尺度(等級)、離散変数(兄弟姉妹・配偶者の数、両親・子供の数)のみ扱う。

#データフレームの引数に属性を入れると、その属性のみを示したデータセットが表示される。
In [27]: train_df[['Pclass','Survived']]
Out[27]:
     Pclass  Survived
0         3         0
1         1         1
2         3         1
3         1         1
4         3         0
..      ...       ...
886       2         0
887       1         1
888       3         0
889       1         1
890       3         0

[891 rows x 2 columns]

#等級と生存率には高い相関が確認された。
#よって、等級を予測モデルの属性に含める。
In [30]: train_df[['Pclass','Survived']].groupby(['Pclass'],as_index=False).mean().
    ...: sort_values(by='Survived', ascending=False)
Out[30]:
   Pclass  Survived
0       1  0.629630
1       2  0.472826
2       3  0.242363

#性別と生存率も高い相関が確認された。
In [31]: train_df[['Sex','Survived']].groupby(['Sex'],as_index=False).mean().sort_v
    ...: alues(by='Survived',ascending=False)
Out[31]:
      Sex  Survived
0  female  0.742038
1    male  0.188908

#兄弟姉妹・配偶者の数(SibSp)と両親・子供の数(Parch)は幾つかの属性値で、相関が0である。
#そのため、14.4.作成(Creating)に示したとおり、家族(Family)という新しい属性を作ってから分析した方がいいかもしれない。
In [34]: train_df[['SibSp','Survived']].groupby(['SibSp'],as_index=False).mean().so
    ...: rt_values(by='Survived',ascending=False)
Out[34]:
   SibSp  Survived
1      1  0.535885
2      2  0.464286
0      0  0.345395
3      3  0.250000
4      4  0.166667
5      5  0.000000
6      8  0.000000

In [36]: train_df[['Parch','Survived']].groupby(['Parch'],as_index=False).mean().so
    ...: rt_values(by='Survived',ascending=False)
Out[36]:
   Parch  Survived
3      3  0.600000
1      1  0.550847
2      2  0.500000
0      0  0.343658
5      5  0.200000
4      4  0.000000
6      6  0.000000
16.データを視覚化する。

・視覚化によって、引き続き今までの観測と推測を確認する。

#定量型属性の相関を確認する。
#生存率と年齢の関係を確認する。
In [51]: g=sns.FacetGrid(train_df,col='Survived')

In [52]: g.map(plt.hist, 'Age',bins=20)
Out[52]: <seaborn.axisgrid.FacetGrid at 0x7f3d106e34e0>

#4歳以下の子どもの生存率は高い。
#80歳の乗客は生き残った。
#15歳から25歳の乗客の多くは亡くなった。

#★この分析の結論
#年齢を予測モデルに組み込むべき。
#年齢がNull値のデータは補完する必要がある。
#年齢を一定のグループ分けにするべき。

f:id:tropicbird:20190722205744p:plain

#定量型属性と順序尺度属性の相関を確認する。
In [54]: grid=sns.FacetGrid(train_df,col='Survived',row='Pclass',height=2.2,aspect=
    ...: 1.6)

In [55]: grid.map(plt.hist,'Age',alpha=.5,bins=20)
Out[55]: <seaborn.axisgrid.FacetGrid at 0x7f3cfb63f390>

In [56]: grid=sns.FacetGrid(train_df,col='Survived',row='Pclass',height=2.2,aspect=
    ...: 1.6)

In [57]: grid.map(plt.hist,'Age',alpha=.5,bins=20)
Out[57]: <seaborn.axisgrid.FacetGrid at 0x7f3cfb63f5f8>

In [58]: grid.add_legend()
Out[58]: <seaborn.axisgrid.FacetGrid at 0x7f3cfb63f5f8>
#乗客は等級3が最も多く、亡くなった乗客も等級3が多い。
#等級2と3の幼児の大半は生き残った。
#等級1の乗客の多くは生き残った。
#各等級内の年齢の分布は異なる。

#★この分析の結論
#等級を予測モデルに取り込む。

f:id:tropicbird:20190722205719p:plain

#定性データの相関
In [60]: grid=sns.FacetGrid(train_df, row='Embarked',height=2.2,aspect=1.6)

In [61]: grid.map(sns.pointplot,'Pclass','Survived','Sex',palette='deep',order=[1,2,3],hue_order=['male','female'])
Out[61]: <seaborn.axisgrid.FacetGrid at 0x7f3cfb775ac8>

In [62]: grid.add_legend()
Out[62]: <seaborn.axisgrid.FacetGrid at 0x7f3cfb775ac8>

#女性は男性よりも生存率が高い。
#港Cからの乗客は例外的に男性の方が生存率が高い。これは、港と等級の相関がある可能性を示唆している。
#港Cと港Qの等級3の生存率は比較的高い。
#港と生存率を大きく相関している。

#★この分析の結論
#性別を予測モデルに取り入れる。
#港属性のデータのNull値を埋め、港属性を予測モデルに取り入れる。

f:id:tropicbird:20190722205657p:plain

#定性型属性と定量型属性の相関を確認する。
In [64]: grid=sns.FacetGrid(train_df,row='Embarked',col='Survived',height=2.2,aspec
    ...: t=1.6)

In [65]: grid.map(sns.barplot,'Sex','Fare',alpha=.5,ci=None,order=['female','male'])

Out[65]: <seaborn.axisgrid.FacetGrid at 0x7f3cfb25f320>

In [66]: grid.add_legend()
Out[66]: <seaborn.axisgrid.FacetGrid at 0x7f3cfb25f320>

#高い料金を支払っている乗客は生存率が高い。料金をカテゴリー化したデータを作る。
#港と生存率は相関がある。港のNull値を埋める。

#★この分析の結論
#定量データの料金を区分化したデータを新たに作成する。

f:id:tropicbird:20190722205630p:plain