PandasのDataFrameでDatetimeIndexを曜日順に並びかえるの巻
PandasのDataFrameでDatetimeIndexから取得した曜日を曜日順に並べる方法のメモ
経緯
Datetimeindexからweekday_nameを取得してソートするとアルファベット順になるので月火水・・・でソートさせてください。。。
↓こういうDataFrame(weekdayとyearがDatetimeIndex,のMultiindex, kmがcolumn)があったときに。。。
km
weekday year
Tuesday 2019 11.7
Wednesday 2019 12.4
Thursday 2019 8.7
Friday 2019 14.8
Saturday 2019 3.0
Sunday 2019 9.5
Monday 2019 1.3
↓このように曜日でソートしたいっていうだけなんですけど。。。
km
weekday year
Monday 2019 1.3
Tuesday 2019 11.7
Wednesday 2019 12.4
Thursday 2019 8.7
Friday 2019 14.8
Saturday 2019 3.0
Sunday 2019 9.5
↓普通にsort_indexを使うと。。。あら、アルファベット順に並んじゃって全然ピンとこない。。。月火水木金土日で並べたいだけなんじゃあたしは。
km
weekday year
Friday 2019 14.8
Monday 2019 1.3
Saturday 2019 3.0
Sunday 2019 9.5
Thursday 2019 8.7
Tuesday 2019 11.7
Wednesday 2019 12.4
っていう話。
やり方
csvデータの読み込みから並びかえて出力するまでの一通りの手順を記載します。
データ読み込み
y-m-d,km
2019/7/30,11.7
2019/7/31,12.4
2019/8/1,8.7
2019/8/2,14.8
2019/8/3,3
2019/8/4,9.5
2019/8/5,1.3
これはワタシのジョギングの記録を一週間分抜粋したものです。(日付, 走行距離のcsvファイル; distance.csv)。
これを曜日ごとに走った距離をまとめてみよう、という試みです。ちなみに7月30日は火曜日でした。
とりあえずpandasで読み込んでDataFrameにします
#!/usr/bin/env python
# coding: utf-8
#pandasをpdとして読み込む
import pandas as pd
#read_csvメソッドでCSVファイルを読み込んでpandasのdataframeとする。これをdfとした。
#csvファイル(distance.csv)は期間2019.7.20-2019.8.5でジョギングした距離を記録したもの
#pandasで読み込み。
#コンマで分ける。日付はparseしてDatetime型とし、最初の要素(y-m-d)をindexに指定してDatetimeIndexとする。
df = pd.read_csv("distance.csv", sep="," , parse_dates= True, index_col=0)
#データを表示して確認する
print(df)
km
y-m-d
2019-07-30 11.7
2019-07-31 12.4
2019-08-01 8.7
2019-08-02 14.8
2019-08-03 3.0
2019-08-04 9.5
2019-08-05 1.3
一応データ型を確認してみる
# 各列のデータ型を確認
print('dateframeの列のデータ型>>>\n', df.dtypes)
print()
# indexの確認
print('indexは>>>\n', df.index)
print()
# columnの確認
print('columnは>>>\n', df.columns)
日付の列がちゃんとDatetimeIndexになってます。よしよし、これで曜日名が取り出せる。
dateframeの列のデータ型>>>
km float64
dtype: object
indexは>>>
DatetimeIndex(['2019-07-30', '2019-07-31', '2019-08-01', '2019-08-02','2019-08-03'],
dtype='datetime64[ns]', name='y-m-d', freq=None)
columnは>>>
Index(['km'], dtype='object')
曜日名を取り出してMultiindex化する
#index.weekday_nameで曜日名、index.yearで年を取り出してindexとし、multiindex化しておく
df_weekdayname = df.set_index([df.index.weekday_name, df.index.year])
#確認
print(df_weekdayname)
km
y-m-d y-m-d
Tuesday 2019 11.7
Wednesday 2019 12.4
Thursday 2019 8.7
Friday 2019 14.8
Saturday 2019 3.0
Sunday 2019 9.5
Monday 2019 1.3
#index名をわかりやすいものに変更。
df_weekdayname.index.names = ['weekday', 'year']
#確認
print(df_weekdayname)
km
weekday year
Tuesday 2019 11.7
Wednesday 2019 12.4
Thursday 2019 8.7
Friday 2019 14.8
Saturday 2019 3.0
Sunday 2019 9.5
Monday 2019 1.3
このままだと見にくいので並べ替えたい、と。
でもsort_indexして並べ替えると、冒頭のようにアルファベット順に並んでしまう。。。
そういうわけで以下の方法で並べかえました。他にやり方あるかも知らんですが。
曜日を月火水・・・の順で並べ替える
月火水で並べた曜日のリストを作っておいて、reindexにて元あったindexと差しかえます。
levelでMultiindexのweekdayのほうを指定し、labelsに用意しておいたyoubiを入れます。
#曜日のリストを作っておく
youbi = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
#曜日をちゃんと並ぶように並びかえる。これをtatemukiとした。
tatemuki = df_weekdayname.reindex(level='weekday', labels=youbi)
#確認
print(tatemuki)
↓これでよしと。
km
weekday year
Monday 2019 1.3
Tuesday 2019 11.7
Wednesday 2019 12.4
Thursday 2019 8.7
Friday 2019 14.8
Saturday 2019 3.0
Sunday 2019 9.5
ついでにmatplotlibで視覚化してみる。
#matplotlibで視覚化してみる
import matplotlib as mpl
import matplotlib.pyplot as plt
#種類を棒グラフ、legend(凡例)なし。
ax = tatemuki.plot(kind ='bar', legend=False)
#X軸の目盛ラベルをtatemuki.index.levels[0](曜日)にする
ax.set_xticklabels(tatemuki.index.levels[0])
#X軸ラベルは無し、Y軸ラベルはKm, 種類はbar
ax.set_xlabel('')
ax.set_ylabel('Km')
ax.plot(kind = 'bar')
#サイズオーバーの際に見切れないように表示する
plt.tight_layout()
#表示する
plt.show()
曜日ごとのデータを見やすい状態で確認できるようになりました。
ちなみに横向きの表を並べ替える場合
↓これ(df_weekdayname)を
weekday year
Friday 2019 14.8
Monday 2019 1.3
Saturday 2019 3.0
Sunday 2019 9.5
Thursday 2019 8.7
Tuesday 2019 11.7
Wednesday 2019 12.4
横向きにして、
#reset_index().pivotにてyearをindexに、weekdayをcolumnに振り直す。kmはvaluesのまま。
df_weekdayname_reset = df_weekdayname.reset_index().pivot('year', 'weekday', 'km')
weekday Friday Monday Saturday Sunday Thursday Tuesday Wednesday
year
2019 14.8 1.3 3.0 9.5 8.7 11.7 12.4
並べ替え。
#reindexを使用して、先ほど用意しておいたyoubiに差し替え。横向き(行方向)なのでaxis=1を指定。
yokomuki = df_weekdayname_reset.reindex(youbi, axis=1)
weekday Monday Tuesday Wednesday Thursday Friday Saturday Sunday
year
2019 1.3 11.7 12.4 8.7 14.8 3.0 9.5
または次のやり方でも
pd.DataFrame(df_weekdayname_reset).loc[:, youbi]
もしくは
pd.DataFrame(df_weekdayname_reset).loc[:, ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']]
でいける。めでたしめでたし。
このブログはエックスサーバー で運営しております。
WordPressを使うならロリポップ!
簡単インストール完備で楽々スタート!
世界にたった一つ、あなただけのドメインを登録しよう!
格安ドメイン取得サービス─ムームードメイン─