tsfreshで時系列データの統計的処理を簡単に


# 概要
時系列データを処理する機会があり、便利そうなものを発見したので、使い方のメモ。

以下の公式を参照。
[tsfresh](https://tsfresh.readthedocs.io/en/latest/index.html)
> tsfresh is a python package. It automatically calculates a large number of time series characteristics, the so called features. Further the package contains methods to evaluate the explaining power and importance of such characteristics for regression or classification tasks.


# 使い方
以下はJupyter Notebook上で実行しています。

## ライブラリのインポート

```py
!pip install tsfresh
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
```

## 時系列データの作成
適当なダミーデータを作成。

```py
timeline = np.arange(10000)

data = np.sin(timeline/100) + np.cos((timeline/100) * 3) + (np.random.rand(len(timeline)))*0.2

plt.plot(timeline[:1000], data[:1000])
plt.xlabel('time')
plt.ylabel('data')
plt.show()
```

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/c706fc78-0974-0af4-890e-84f028b68f5d.png)


## feature_extractionで特徴量を計算
feature_calculatorsという関数があるので、これを使うと様々な特徴量を計算できる。
[feature_extraction](https://tsfresh.readthedocs.io/en/latest/api/tsfresh.feature_extraction.html)


```py
import tsfresh.feature_extraction.feature_calculators as feature_calculators

range_data = data[:600]


mean_abs_change = feature_calculators.mean_abs_change(data)
# 前後のポイント間での差分の平均値
# np.mean(np.abs(np.diff(x))) と等しい

first_location_of_maximum = feature_calculators.first_location_of_maximum(data)
# 最大値が観測される位置

fft_aggregated = feature_calculators.fft_aggregated(data, [{'aggtype': 'skew'}])
# フーリエ変換

number_peaks = feature_calculators.number_peaks(data[:1000], 50)
# ピークの数

index_mass_quantile = feature_calculators.index_mass_quantile(data[:1000], [{'q': 0.5},{'q': 0.1}])
# パーセンタイル処理

linear_trend = feature_calculators.linear_trend(range_data, [{'attr': "slope"},{'attr': 'intercept'},{'attr': 'rvalue'}])
# 単純なトレンド分析。attrに関しては下記を参照
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.linregress.html

autocorrelation = feature_calculators.autocorrelation(data, 100)
# 自己相関の計算
```

この中のlinear_trendを使って、時系列データのトレンドを計算してみる。

```py
trend = linear_trend[0][1] * timeline + linear_trend[1][1]

plt.plot(timeline[:600], data[:600])
plt.plot(timeline[:600], trend[:600])
plt.xlabel('time')
plt.ylabel('data')
plt.show()
```

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/3e1d69db-a85f-1b16-4d3d-77a031dd8329.png)

当たり前だが、正しく計算できていそう。

# まとめて特徴量を計算
個別にではなくて、とりあえずたくさん特徴量を計算したい場合は、extract_featuresを使えばよさそう。

```py
from tsfresh import extract_features

# こちらはDataFrameではないといけないようなので変換する。
# 1つのデータフレーム内に複数の時系列データがある形を想定しているらしく、どのデータが時系列としてひとまとまりなのか識別するカラムが必要(column_idで指定)
# 今回は1種類しか入っていないので、すべて1にした
temp = pd.DataFrame(data, columns=['value'], dtype='float')

temp['id'] = 1
temp.head()

extracted_features = extract_features(temp, column_id='id')
display(extracted_features.columns)
```

```py
Index(['value__abs_energy', 'value__absolute_sum_of_changes',
       'value__agg_autocorrelation__f_agg_"mean"__maxlag_40',
       'value__agg_autocorrelation__f_agg_"median"__maxlag_40',
       'value__agg_autocorrelation__f_agg_"var"__maxlag_40',
       'value__agg_linear_trend__f_agg_"max"__chunk_len_10__attr_"intercept"',
       'value__agg_linear_trend__f_agg_"max"__chunk_len_10__attr_"rvalue"',
       'value__agg_linear_trend__f_agg_"max"__chunk_len_10__attr_"slope"',
       'value__agg_linear_trend__f_agg_"max"__chunk_len_10__attr_"stderr"',
       'value__agg_linear_trend__f_agg_"max"__chunk_len_50__attr_"intercept"',
       ...
       'value__symmetry_looking__r_0.9',
       'value__symmetry_looking__r_0.9500000000000001',
       'value__time_reversal_asymmetry_statistic__lag_1',
       'value__time_reversal_asymmetry_statistic__lag_2',
       'value__time_reversal_asymmetry_statistic__lag_3',
       'value__value_count__value_-1', 'value__value_count__value_0',
       'value__value_count__value_1', 'value__variance',
       'value__variance_larger_than_standard_deviation'],
      dtype='object', name='variable', length=794)
```

これだけで794個も特徴量が計算できたらしい。

# まとめ
numpy1行で終わるようなものも多いが、まとめて特徴量計算したいときには便利かもしれない。特にextract_features。
時間を見つけてもう少し使ってみたい。