４０代おっさんPythonを勉強する（データ解析,Pandas編②）

## 本記事について

この記事はプログラミング初学者の私が学んでいく中でわからない単語や概要を分かりやすくまとめたものです。
もし不正などありましたらコメントにてお知らせいただければ幸いです。

## 前回の記事

<https://qiita.com/kou1121/items/5c3a5d490ff041416bee>

## データフレーム(DataFrame)オブジェクト

- データを操作するためのオブジェクト
- 高速で効率的に操作できる
- 多様なデータフォーマットと相互的に読み書きできる
  - CSV, Excel, SQLデータベース, JSONなど
- データの集計やグラフの作成ができる

### データセット

- 気象庁（[http://www.data.jma.go.jp/obd/stats/etrn/index.php](http://www.data.jma.go.jp/obd/stats/etrn/index.php)）から福岡市の１３２年間の月別の[日平均気温](https://www.data.jma.go.jp/obd/stats/etrn/view/monthly_s3.php?prec_no=82&block_no=47807&year=&month=&day=&view=a1)のデータを取得
- Excelファイルにデータを保存しておく（weather_data.xlsx）
- Pandasから直接データを読み込む

```python
#  1890年から2021年まで福岡市の気温
import pandas as pd

#  Excelファイルの読み込んでデータフレームに格納
df = pd.read_excel('weather_data.xlsx', index_col=0) # インデックスのカラムを指定
df
```

`No module named 'pandas'`こちらが出た場合は
`pip install pandas`をインストール

`ImportError: Missing optional dependency 'openpyxl'. Use pip or conda to install openpyxl.`
`pip install openpyxl`をインストール

- データフレームからデータを確認

```python
#  先頭から
df.head() # ()の中に表示したい行数を入れてもいい
```

```python
#  後尾から
df.tail() # ()の中に表示したい行数を入れてもいい
```

```python
#  後尾から
df.tail() # ()の中に表示したい行数を入れてもいい
```

```python
# 自動集計
# 平均、偏差値、最小値、最大値、中央値など
df.describe()
```

```python
#  インデックス、行のラベル
df.index
```

```python
#  列のラベル
df.columns
```

### グラフやチャートを作成

- 何も考えず、データフレームにあるすべてのデータを折れ線にする

```python
#  全てのデータを表示
df.plot()
```

- グラフとしては情報が足りないので、少し情報を加えよう

```python
#  Dataframeでできる設定
ax = df.plot(title='1890年から2021年まで福岡市の気温',  # タイトル
             grid=True, # 網線の有無
             figsize=(12, 8), # グラフのサイズ
             legend=True, # 凡例の有無
             xlabel='1890年～2021年', # x軸とy軸のラベル
             ylabel='気温(℃)')
```

 Dataframeの設定が限られているが、BackendはMatplotlibなので、さまざまな設定ができる

- Dataframeでできる設定
  - [https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.html#pandas.DataFrame.plot](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.html#pandas.DataFrame.plot)
- MatplotlibのAxesオブジェクトを使う設定
  - [https://matplotlib.org/stable/api/axes_api.html](https://matplotlib.org/stable/api/axes_api.html)

```python
#  Axesオブジェクトを返り値として代入
ax = df.plot(title='1890年から2021年まで福岡市の気温',  # タイトル
             grid=True,  # 網線の有無
             figsize=(12, 8),  # グラフのサイズ
             legend=True,  # 凡例の有無
             xlabel='年',  # x軸とy軸のラベル
             ylabel='気温（℃）')

#  Axesオブジェクトを使う
ax.legend(loc='upper right', title='月', bbox_to_anchor=(1.15, 0.5))  # 凡例の場所、タイトルなどを設定
ax.annotate('年の値', xy=(2021, 18.2), xytext=(2030, 18.5), arrowprops={'arrowstyle':'->'}, 
            fontsize=12, annotation_clip=False)  # 年の値の場所を示す

#  グラフをファイルに保存できる
plt.savefig('linechart.pdf', format='pdf', bbox_inches='tight')  # pdf形式
#plt.savefig('linechart.png', format='png', bbox_inches='tight')  # png形式
#plt.savefig('linechart.jpg', format='jpg', bbox_inches='tight')  # jpg形式
# 他のsvg, gif ... などもできる
# pdfが一番綺麗にできているからおすすめ
```

### 部分的なデータで可視化

- 一部だけのデータでグラフを作成することができる
- カラムのラベルや、インデックスを利用して部分的なデータを取り出す

```python
# '年の値'だけを取り出してプロット
df1 = df['年の値'] # 一つのカラム
df1.plot(title='1890年から2021年まで福岡市の平均気温') # 温暖化がわかる
```

```python
# 2000年以降の1月から12月までのデータ
# .locで行列を指定
df2 = df.loc[2000:, '1月':'12月'] 
df2.plot(title='2000年以降の福岡市の気温', legend=False, xticks=[2000, 2005, 2010, 2015, 2020], grid=True)
```

`[2000:, '1月':'12月']`
`2000:`右側が行の指定2,000年以降から
`'1月':'12月'`左側が列の指定

```python
#  10年ごとのデータだけ取り出す
#  スライシングを利用
df2 = df.loc[::10, '1月':'12月']
df2.plot(title='2000年以降の福岡市の気温', legend=False, grid=True)
```

### 行列を逆にする

- `.T`で行列を逆にするができる

```python
dfX = df.T
dfX
```

```python
#  全ての逆データを表示
dfX.plot(legend=False)
```

```python
#  2000年のデータだけ棒グラフにする
dfX1 = dfX[2000]['1月':'12月']
dfX1.plot.bar(title='2000年の年間気温')
```

```python
#  1900, 1960, 2020年のデータだけ折れ線にする
dfX1 = dfX.loc['1月':'12月', [1900, 1960, 2020]]
dfX1.plot(title='1900年、1960年、2020年の年間気温比較')
```

```python
# 横棒グラフにする
dfX1 = dfX[[1890, 2020]]['1月':'12月']
dfX1.plot.barh()
```

```python
# 1890年と2020年の気温を散布図で比較
dfX1 = dfX[[1890, 2020]]['1月':'12月']
dfX1.plot.scatter(x=2020, y=1890)
dfX1.plot.scatter(x=2020, y=1890, s=60, c=2020, cmap='rainbow')
```

- Colormapsはこちらへ
  - [https://matplotlib.org/tutorials/colors/colormaps.html](https://matplotlib.org/tutorials/colors/colormaps.html)

### 他のグラフ

- ヒストグラム(度数分布図)

```python
#  130年間2月の温度の分布
df1 = df['2月']
df1.plot.hist(bins=[1,2,3,4,5,6,7,8,9,10], alpha=0.5)
```

```python
#  130年間1月,2月,3月の温度の分布
df1 = df[['1月','2月','3月']]
df1.plot.hist(bins=20, alpha=0.5)
```

- ヒスとグラムのような集計をして、円グラフを作成

```python
df1 = df['2月']
df2 = df1.value_counts(bins=[0,3,4,5,6,7,8,9,10]) # 気温をグループに分ける
df2 = df2.sort_index().to_frame() # 集計を並び替えてデータフレームに納める
df2.index = ['<3℃','3~4℃','4~5℃','5~6℃','6~7℃','7~8℃','8~9℃','9~10℃',] # インデックスのラベルを変える
df2
df2.plot.pie(y='2月', title='2月の平均温度', legend=False, figsize=(5, 5), autopct='%.1f%%', 
             startangle=0, counterclock=False)
```

## 参考

https://www.kitakyu-u.ac.jp/news/2022/08/003215.html