1.1. csvファイルを読み込む

ここでは、csvファイルの読み込みを説明します。
Pythonを学習していく上でデータインポートは必須であり、`print()`文や`for文`を覚えたら、次に知りたいのが、データファイルのインポートのはずです。

#**トピック**

- **1. pandasでcsvファイルを読み込む**: `pd.read_csv()`
- **2. pandasで行、列の範囲を指定して csvを読み込む**<br>
**2.1 日本語を含んだファイルの場合**: `pd.read_csv(encoding="shift_jis")`<br>
**2.2 範囲を指定する**: `pd.read_csv(skiprows=, skipfooter=, usecols=)`
- **3. 日付をindexとして読み込む**: `pd.read_csv(parse_dates=True)`
- **まとめ**<br>
**ポイント整理**
- **参考ページ**
<br>https://shilabo.com/python/web_self/
<br>https://note.nkmk.me/python-pandas-read-csv-tsv/
<br>https://qiita.com/sakabe/items/ae1fa47a58c796006627

---
読み込むファイルはcsv形式(.csv)が好んで用いられます。csvは書式がなく、扱いやすいのです。
Excel(.xlsx)を読み込む事も多いですが、まずはcsv形式を習得する事が重要です。
csvが読み込めれば、Excelもほぼ同じ手順でできます。

後で見るように、**Pythonは日本語がひどく苦手**です。インポートするデータは英語だけにしておくべきです。

データのインポートが出来ないと、何も出来ないに等しいです。

尚、当サイトではよく使う部分のみを説明し、詳細は他のHPに譲ることにします。
例えば、以下のサイトが非常に役に立ちます。極めて質の高い無料のサイトです。

https://note.nkmk.me/python-pandas-read-csv-tsv/

#1. pandasでcsvファイルを読み込む
csvの読み込みは、pandasの`pd.read_csv()` を使います。

これを使う為に最初に`import pandas as pd`と書きます。

読み込んだデータは基本DataFrameとなります。
ここでは、以下のようなcsvファイルを読み込みます。

データはA列が行の名前、B～D列がカラム名（列名）です。
通常、このようにデータには、行の名前(11, 12, 13)と列名（clm1, clm2, clm3）が付いています。列名はヘッダー(header)と呼ばれます。

これを、行の名前が(11, 12, 13)となるように、読み込もうと思います。DataFrameとして読み込んだ、行の名前のことをindexといいます。

以下のリンク（GitHub : 外部サイト）を右クリックして「名前を付けてリンク先を保存」か、一度開いてメモ帳にコピペして保存してください。その際に、拡張子が自動で「.txt」となりますが、「.csv」とタイプして保存してください。

[a001_001a.csv](https://gist.githubusercontent.com/shilabo/e3813a6f04cbd788a9d18a3f42ac6f86/raw/9383a1986c7f04aa83712f6034148d36021843b2/a001_001a.csv)

```
ID,clm1,clm2,clm3
11,1863,7911,2634
12,1850,8000,2623
13,1853,7980,2578
```

Pythonでは `pd.read_csv(‘ファイルのパス’) `で読み込みます。
ファイルのパスは、例えば、Windowsのドキュメントに保存した場合、

`C:\Users\ユーザ名\Documents`

となります。以下はユーザー名が “shilabo” で、ドキュメントフォルダの中に “SHiLABO_python” というフォルダを作った場合です。
パスを指定する場合”r”を頭に書くと\を\\と書く必要がなくなり便利です。Windowsのエクスプローラーからパスをコピーして、そのままペーストするだけよくなります。

```Python
import pandas as pd
df1a = pd.read_csv(r'C:\users\shilabo\documents\price1_01.csv')
print(df1a)
#   ID  clm1  clm2  clm3
#0  11  1863  7911  2634
#1  12  1850  8000  2623
#2  13  1853  7980  2578
```

あるいは、パスとファイル名を分けた方がいい場合があります。例えば、ループ(for文)で同じパスの複数のファイルを読み込みたい場合です。
その為、実務では以下のように書くことがあります。

```Python
p1 = r'C:\Users\shilabo\Documents\SHiLABO_python'
f1 = 'a001_001a.csv'
p1f1 = p1 +'\\'+f1
df1b = pd.read_csv(p1f1)
print(df1b)
#   ID  clm1  clm2  clm3
#0  11  1863  7911  2634
#1  12  1850  8000  2623
#2  13  1853  7980  2578
```

結果はどちらも同じです。
ただし、これでは目的が達成されていません。indexが自動で0,1,2と振られ、A列の11, 12, 13はデータとして扱われています。本来はA列の11, 12, 13をindexにしたかったはずです。

そこで、オプションの`index_col=0, header=0`を使います。デフォルトは`header=0`なので、これは省略できます。

```Python
df1c =pd.read_csv(p1f1, index_col=0, header=0)
print(df1c)
#    clm1  clm2  clm3
#ID
#11  1863  7911  2634
#12  1850  8000  2623
#13  1853  7980  2578
```

indexはカラム名(列名)で指定することもできます。以下は、’clm1’をindexにした場合です。

```Python
df1d =pd.read_csv(p1f1, index_col='clm1', header=0)
print(df1d)
#      ID  clm2  clm3
#clm1
#1863  11  7911  2634
#1850  12  8000  2623
#1853  13  7980  2578
```

#2. pandasで行、列の範囲を指定してcsvを読み込む
##2.1 日本語を含んだファイルの場合
しかし、現実には、このように元がきれいなデータである事は少なく、多くの場合、次のように、余計なものが含まれています。（GitHubのリンクa001_001b.csvをクリックすると形が見えます）

しかも、日本語の嵐。Pythonは日本語が苦手です。
欲しいのは、セル「B4:E7」の範囲だけです。

https://gist.github.com/shilabo/6329cf4d579360bd29e0808c5aed0d96

```
部署,金融商品開発部,,,
作成日,2021/3/24,,,
,,,,
,ID,A,B,C
,11,1863,7911,2634
,12,1850,8000,2623
,13,1853,7980,2578
,,,,
*1: Aの参照期間は…。,,,,
*2: Bは〇〇の配当あり。,,,,
```

これもpandasの`pd.read_csv()`で読み込みますが、日本語を含む場合、オプションに`encoding='shift_jis'` を指定します。<br>
“shift”と”jis”の間はアンダースコア(_)であり、ハイフン(-)ではありません。
これを間違い、データが読めないと悩む人が多いです。因みに、他に英語を読み取る`encoding = 'utf-8'`がありますが、こちらはハイフン(-)です。

とりあず`encoding='shift_jis'`を指定して実行すると、以下のようになります。

```Python
f2 = 'a001_001b.csv'
p1f2 = p1 + '\\' + f2 # p1 = r'C:\Users\shilabo\Documents\SHiLABO_python'
df2a = pd.read_csv(p1f2, encoding='shift_jis') # encoding='shift_jis'　が必要
print(df2a)
#               部署    金融商品開発部 Unnamed: 2 Unnamed: 3 Unnamed: 4
#0             作成日  2021/3/24        NaN        NaN        NaN
#1             NaN        NaN        NaN        NaN        NaN
#2             NaN         ID          A          B          C
#3             NaN         11       1863       7911       2634
#4             NaN         12       1850       8000       2623
#5             NaN         13       1853       7980       2578
#6             NaN        NaN        NaN        NaN        NaN
#7   *1: Aの参照期間は…。   NaN        NaN        NaN        NaN
#8  *2: Bは〇〇の配当あり。 NaN        NaN        NaN        NaN
```

読み込めていますが、csv上で空白も読み込み(NaN)、不必要なデータ（日本語部分）も読み込んでいます。これは意図とは異なります。データだけが必要なのです。むしろ、データ以外は取り込んではいけない、と言った方がいいでしょう。

##2.2 範囲を指定する
そこで範囲を指定する為に、以下のオプションを指定します。

`skiprows=3` : 最初の3行はスキップ(1～3行目)
`skipfooter=3` : 下から3行はスキップ(8～10行目）
`usecols=range(1,5)` : 列の指定(Python上での1列～4列目 = csv上では2列目(B列)から5列目(F列))

`skipfooter=`でWarningが出た場合、更にオプションで `engine='python'`を指定します。

ここで、`usecols=`について説明します。

`range(1,5)`と書くと、0始まりのPythonから見て、1, 2, 3, 4列目となります。
つまり0列目はスキップし、1, 2, 3, 4列目を読み、5列目は含みません。
csv上では普通1, 2, 3…列と数えるし、終わりの5も含むか含まないか、この感覚が難しいです。
実際には、`print()`で意図通りか必ず確認します。

また、`index_col=0`は`usecols`で切り取った後の、Pythonの0列目をindexにする、という意味です。
同様に、`header=0`は、`skiprows`で切り取った後の、Pythonの0行目をヘッダーにする、という意味です。

Pythonは基本0で始まります(1ではない）。

```Python
df2b= pd.read_csv(p1f2, encoding='shift_jis', skiprows=3, skipfooter=3, usecols=range(1,5), index_col=0, header=0, engine='python') #engine='python'で実行できる #
print(df2b)
#       A     B     C
#ID
#11  1863  7911  2634
#12  1850  8000  2623
#13  1853  7980  2578
```

usecols の範囲はリストで指定することもできます。
この例の場合、`usecols=[1,2,3,4]`。ここでも、0始まりを意識しましょう。

```Python
df2c= pd.read_csv(p1f2, encoding='shift_jis', skiprows=3, skipfooter=3, usecols=[1,2,3,4], index_col=0, header=0, engine='python')
print(df2c)
#       A     B     C
#ID
#11  1863  7911  2634
#12  1850  8000  2623
#13  1853  7980  2578
```

#3. 日付をindexとして読み込む
日付がある時系列データを読み込む場合、”型”をdatetime型として読み込むと便利です。

`index_col=`でindexとするカラム名（列名）を指定し、`parse_dates=True`のオプションを指定します。

以下のcsvファイルを読み込んでみます。(GitHubのa001_001c.csvのリンクをクリックすると形が見えます。)

https://gist.github.com/shilabo/4dc9c180ba99e8593bd19a4c0e1aa392

```
ValDate,clm1,clm2,clm3
1999/1/1,1863,7911,2634
1999/2/12,1850,8000,2623
1999/3/23,1853,7980,2578
2005/1/23,1858,7905,2578
2005/2/12,1873,7952,2578
2005/3/1,1844,7820,2599
2021/1/12,1820,7480,2556
2021/2/23,1885,7349,2557
2021/3/1,1879,7199,2569
```

```Python
f3 = 'a001_001c.csv'
p1f3 = p1 + '\\' +f3 #p1　=r'C:\Users\shilabo\Documents\SHiLABO_python'
df3 = pd.read_csv(p1f3, index_col='ValDate',parse_dates=True)
print(df3)
#            clm1  clm2  clm3
#ValDate
#1999-01-01  1863  7911  2634
#1999-02-12  1850  8000  2623
#1999-03-23  1853  7980  2578
#2005-01-23  1858  7905  2578
#2005-02-12  1873  7952  2578
#2005-03-01  1844  7820  2599
#2021-01-12  1820  7480  2556
#2021-02-23  1885  7349  2557
#2021-03-01  1879  7199  2569
```

indexをdatetime型にすると、df.index.year == , df.index.month == , df.index.day ==と書くことで、年、月、日でフィルターをかけることができます。
以下は、1999年だけ、2月だけ、23日だけ、の例です。

```Python
print(df3[df3.index.year == 1999])
#            clm1  clm2  clm3
#ValDate
#1999-01-01  1863  7911  2634
#1999-02-12  1850  8000  2623
#1999-03-23  1853  7980  2578

print(df3[df3.index.month == 2])
#            clm1  clm2  clm3
#ValDate
#1999-02-12  1850  8000  2623
#2005-02-12  1873  7952  2578
#2021-02-23  1885  7349  2557

print(df3[df3.index.day == 23])
#            clm1  clm2  clm3
#ValDate
#1999-03-23  1853  7980  2578
#2005-01-23  1858  7905  2578
#2021-02-23  1885  7349  2557
```

年、年月の指定ならば、以下のように`df['1999']`や`df['2021-02']`でも可能です。

```Python
print(df3['1999'])
#             clm1  clm2  clm3
#ValDate
#1999-01-01  1863  7911  2634
#1999-02-12  1850  8000  2623
#1999-03-23  1853  7980  2578
```

```Python
print(df3['2021-02'])
#             clm1  clm2  clm3
#ValDate
#2021-02-23  1885  7349  2557
```

indexをdatetime型にした場合の使い方は、次のサイトが詳しいです。

https://qiita.com/sakabe/items/ae1fa47a58c796006627

#まとめ
`pd.read_csv()`にいくつもオプションを指定すれば、不要なものを含むcsvファイルもデータとして読み込めます。しかし、とても面倒です。
現実には難しいですが、**出来れば、読み込むcsvファイルの不要部分を削除し、シンプルなデータ形式にしておくのがいいです。その方が時間が省略できます**。

また、**日本語が含まれると、エラーの原因になり**、その解決に時間が掛かるので、可能ならば**日本語は避けた方がいい**です。

## ポイント整理
- `pd.read_csv()`を使う。
- 日本語を含む場合、`encoding='shift_jis'`をオプションに指定する。
- `skiprows=, skipfooter=`で上下の範囲（行）を指定できる。
- `skipfooter=`でエラーが出たら`engine='python'`を指定する。
- `usecols=`で左右（列）の範囲を指定できる。
- `index_col=`でindexにする列を指定できる。
- indexをdatetime型で読み込む場合、`parse_dates=True`を指定する。

#参考ページ
実践で使っている技術が掲載されています。書籍のように構成されています。

https://shilabo.com/python/web_self/a001_000_read_csv_excel/a001_001/

ここに掲載したコードが全て掲載されています。

https://gist.github.com/shilabo/d57f11c17bc8c8d5ebf6ac904fbe0808

記事内で紹介したページです。

https://note.nkmk.me/python-pandas-read-csv-tsv/

https://qiita.com/sakabe/items/ae1fa47a58c796006627