pandas時系列データの扱い方

# 初めに
pandas初学者の方向けに、時系列データ(日付データ)の扱い方を株価公開データを用いて解説して行きます。なので、データの準備は不要です。自分もデータ分析を始めたばかりで結構躓いたので、これから勉強を始める方の助けになれると嬉しく思います。

## モジュールをインポート
- Pandasは、データを簡単に取り扱う為のデータ操作ツール
- Plotly Expressは、いくつかの公開データセットにアクセスするための便利な関数を提供
```Python
import pandas as pd
import plotly.express as px
```

# ファイルの読み込み

- px.data.stocks()で株価公開データを読み込めます
```Python
df = px.data.stocks()
```
# 時系列データ取り出し方法その１ ＆ 特徴量の作成
```Python
df["year"] = df["date"].apply(lambda x :x.split("-")[0])
df["month"] = df["date"].apply(lambda x :x.split("-")[1])
```
![2023-06-24 134738.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/0f257086-5deb-eb10-4354-24d1c5a134e8.png)
年と月のデータを取り出し、簡単な特徴量の作成をすることができました。

**補足：**
- apply() メソッドは、Pandas ライブラリで提供されているデータフレームやシリーズに対して、特定の関数を要素ごとに適用するために使用されます。<br>
具体的には、各要素に関数を適用して処理を行い、その結果を新しいデータフレームまたはシリーズとして返します。

- lambda 関数は、無名関数または一時的な関数としても知られています。通常の関数とは異なり、関数に名前を付けずに直接定義することができます。主に短い関数や単純な処理に使用されます。
```Python
# lambda 関数ではなく、defで関数を定義した場合
def get_year(date):
    return date.split("-")[0]

def get_month(date):
    return date.split("-")[1]

df["year"] = df["date"].apply(get_year)
df["month"] = df["date"].apply(get_month)
```

# 時系列データその2　datetime型
- datetime 型は、日付と時刻を表現するためのPythonの組み込みモジュールであり、日付や時刻に関連する様々な操作を行うことができます。
***
初めに、データの型を確認します。

```Python
# データフレームの基本的な情報を簡潔に確認することができます。
df.info()
```
![2023-06-24 140755.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/52fcbe90-a37d-323b-5983-4c2b87244b63.png)
dateの型がobjectになっていることが分かります。

datetime型を使う為に、objectからdatetimeに変換します。
```Python
# 'date' 列を datetime 型に変換
df['date'] = pd.to_datetime(df['date'])
```
```Python
df.dtypes
```
![2023-06-24 141327.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/363f3d48-5006-1a5c-37f1-f12b63ea203b.png)

datetime 型に変換することができました。
次はデータを年/月/日ごとに取り出していきます。

```Python
# 'date' 列の年を抽出
df['year'] = df['date'].dt.year
```
![2023-06-24 141728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/76650fb4-4bc6-fa7c-1561-1859744c934c.png)

```Python
# 'date' 列の月を抽出
df['month'] = df['date'].dt.month
```
![2023-06-24 142335.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/355836d6-2b41-9220-07f2-8b7f9a2de1c9.png)

```Python
# 'date' 列の日にちを抽出
df['day'] = df['date'].dt.day
```
![2023-06-24 142438.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/4537b708-7bc2-16fc-f7cc-2c684b9e1f4c.png)

```Python
df.sample(10)
```
![2023-06-24 142714.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/e2d808ee-ec0e-babd-eeba-03786a2e16e9.png)
年/月/日ごとにデータを取り出すことができました。

# 日付のフォーマットの変換について
今回扱った株価公開データは2018-01-31の形で日付データが入っていましたが、20180131の形などでデータが入っていても大丈夫です。

例えば、日付文字列が「20180131」である場合、format='%Y%m%d' と指定することで、それを「年-月-日」の形式に変換して pd.to_datetime() 関数によって datetime 型に変換することができます。
```Python
# 日付文字列を datetime 型に変換
df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')
```
***具体例***
```Python
import pandas as pd

# 日付文字列の列を含むデータフレームを作成
df = pd.DataFrame({'date': ['20160301', '20210518', '19991231']})

# 日付文字列を datetime 型に変換
df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')

# 結果を表示
df['date']
```
![2023-06-24 144745.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/13392149-5acc-a934-b56c-050c4a473cb5.png)

**補足**
format='%Y%m%d' は、日付文字列が「年（4桁）月（2桁）日（2桁）」の形式で表されていることを示すフォーマット指定子です。

format='%Y%m%d'は、%Y は年を4桁で表すための指定子であり、%m は月を2桁で表すための指定子、%d は日を2桁で表すための指定子です。

# 経過日数
.iloc[0,0]でデータの最初の日にちを指定して、引くことで経過日数を計算できます。
```Python
date_df['date'] - date_df.iloc[0,0]
```
![2023-06-24 145658.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/6eca0fd6-c4e8-9de8-0876-fc8686091eb1.png)

元々1週間置きのデータが入っているため、indexが1進むごとに7日経過していることが分かります。
![2023-06-24 150005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/4e1400df-1bae-a413-8dd6-69f46013df31.png)

# 1カ月ごとのデータの合計
```Python
sum_date_AAPL = df.groupby('date')['AAPL'].sum().reset_index()
sum_date_AAPL.set_index('date').resample('M').sum()
```
1カ月間のデータの合計を出すことができます。平均を出す場合は.mean()を使うと出せます。.resample('M')のMをWにすると1週間ごとの合計が出せます。MはMonthのMです。
![2023-06-24 151453.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3482837/39990bc5-a54c-d8e1-a407-3cd0dd6dd986.png)

**補足**
***
**.groupby()** メソッドは、データフレームを指定した列または複数の列でグループ化するために使用されます。グループ化により、同じ値を持つ行が同じグループにまとめられます。グループ化後、各グループに対して集計操作を行うことができます。

例えば、df.groupby('date')['AAPL'] は、'date' 列でデータフレーム df をグループ化し、'AAPL' 列を抽出したグループオブジェクトを作成します。

***
**.reset_index()** メソッドは、データフレームのインデックスをリセットし、新しい連番のインデックスを設定します。リセットされたインデックスは新しい列としてデータフレームに追加されます。

例えば、df.groupby('date')['AAPL'].sum().reset_index() は、'date' 列でグループ化されたデータフレーム df の 'AAPL' 列の値をグループごとに合計し、その結果に新しい連番のインデックスを設定します。
***

# 参考
[ゼロから始めるデータ分析】 ビジネスケースで学ぶPythonデータサイエンス入門](https://www.udemy.com/course/optworks_1/)
[データサイエンスのための実践Pandas](https://www.udemy.com/course/be-a-pandas-pro/)
ChatGPTへの質問

# 終わりに
今回は時系列データの扱い方をご紹介しました。
次回はSIGNATEの練習問題をもとに特徴量の作成についてまとめようと思います。