pandasデータフレームの日付型⇄文字型変換とdfply使用時のメモ

#はじめに
**本記事は、pandasデータフレームの日付型 ⇄ 文字型の変換について**
- 従来の変換方法と注意点
- dfplyライブラリ使用時の変換の注意点
をまとめています。

[dfplyについてのまとめ](https://qiita.com/T_Shinomiya/items/c039451869382e0790f4)の補足記事です。

#事前準備、例データ
```Python:Python：データ
import pandas as pd
import datetime
from dfply import *

#例データ
sales = pd.DataFrame(dict(date=['7/10/17','7/11/17','7/12/17','7/13/17','7/14/17'],
                          date2=['7/10/2017','7/11/2017','7/12/2017','7/13/2017','7/14/2017'],
                          sales=[1220, 1592, 908, 1102, 1395]))
```
![スクリーンショット 2019-01-04 13.30.20.png](https://qiita-image-store.s3.amazonaws.com/0/318124/10a0472d-0a95-15f0-df28-308a54249965.png)

##【従来】 文字型列 → 日付型列に変換
####strptimeで１要素の変換
```Python:Python：strptime()
#strptime()はSeriesには未対応
In [1]:
datetime.datetime.strptime(sales['date2'], '%d/%m/%Y')
#実行結果：エラー（１要素しか変換できない）
Out [1]:
TypeError: strptime() argument 1 must be str, not Intention

#seriesの１要素は変換可能
In [2]:
datetime.datetime.strptime(sales['date2'][0], '%d/%m/%Y')
Out[2]:
datetime.datetime(2017, 10, 7, 0, 0)
```
strptimeはデータフレームの列(series)ごとの変換には対応していなため、その場合pandasのto_datetimeを使います。

####pandasのto_datetimeで列(series)ごとに変換する
```Python:Python：pd.to_dataframe()
sales['pd_date'] = pd.to_datetime(sales['date'], infer_datetime_format=True)
or
sales['pd_date'] = pd.to_datetime(sales['date2'], format='%m/%d/%Y')

sales.dtypes
```
![スクリーンショット 2019-01-04 13.53.07.png](https://qiita-image-store.s3.amazonaws.com/0/318124/1a3923ce-0993-870d-15ba-96378c0a53ad.png)
date               object
date2              object
sales               int64
pd_date    datetime64[ns]
dtype: object

##【従来】 日付型列 → 文字型列に変換
###pandasのdt.strftimeで変換
```Python:Python：pd.dt.strftime()
sales['pd_date_str'] = sales['pd_date'].dt.strftime('%Y-%m-%d')
sales
```
![スクリーンショット 2019-01-13 14.05.18.png](https://qiita-image-store.s3.amazonaws.com/0/318124/0fcaa2ec-a5cc-7ecc-c8e6-7b067b9dcad6.png)


##【dfply】 文字型列 → 日付型列に変換
```Python:Python：dfplyでの日付型変換
#dfplyだとそのまま使えないので、デコレーターを使用し新しい関数を作成
@make_symbolic
def to_datetime(series, infer_datetime_format=True):
    return pd.to_datetime(series, infer_datetime_format=infer_datetime_format)

sales_dfply = sales >> mutate(pd_date=to_datetime(X.date))
```
上記pd.to_datetimeを使用した結果と同様になります。

##【dfply】 日付型列 → 文字型列に変換する
```Python:Python：dfplyでの文字型→日付型変換
sales_dfply = sales >> mutate(pd_date_str=X.pd_date.astype(str))
or
sales_dfply = sales >> mutate(pd_date_str=X.pd_date.dt.strftime('%Y%m%d'))
```
特にデコレーターは必要ありません。astype(str)でそのまま文字型に、dt.strftime()で指定した表記で文字型にもできます。

##【dfply】 日付型列：Ymd HMS → Ymd（時刻等を除いて日付のみにする）
datetime→dateにする（pandas的には結局datetime64）

```Python:Python：dfply　日付型列：YmdHMS　➡　Ymd

#時刻付きデータ（文字型）
date3 = ['7/10/2017 00:00:00','7/11/2017 01:00:00','7/12/2017 02:00:00','7/13/2017 03:00:00','7/14/2017 04:00:00']
sales['date3'] = date3

#日付型に変換（デコレーターto_datetimeで変換）
sales = sales >> mutate(pd_date_HMS = to_datetime(X.date3) )

#さらに日付表示のみ（Ymd）に変換
 #.dt.dateで変換すると文字型になってしまう
 #さらにto_datetimeで日付型に
sales >> mutate(pd_date_Ymd = to_datetime(X.pd_date_HMS.dt.date))
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/318124/660a7175-0ffe-e65f-77cc-f8c1f1d4a5b5.png)
date                   object
date2                  object
sales                   int64
date3                  object
pd_date        datetime64[ns]
pd_date_HMS    datetime64[ns]
pd_date_Ymd    datetime64[ns]
dtype: object


##【dfply】 日差を計算する
```Python:Python：dfplyでの日差を計算
#新しいデータを作成（文字型）
date4 = ['7/10/2017', '7/11/2017', '7/12/2017', '7/13/2017', '7/14/2017']
date5 = ['7/15/2017', '7/18/2017', '7/19/2017', '7/13/2017', '7/10/2017']
new_data = pd.DataFrame({'date4': date4, 'date5': date5})

#日付差を計算（dt.daysで数値型にする）
new_data = new_data >> mutate(
    diff_days=to_datetime(date5) - to_datetime(date4)) >> mutate(
    diff_days_int=X.diff_days.dt.days)
new_data
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/318124/3c1cd18e-a4c1-80e2-7720-ab9290b005c3.png)