【Python】CSVファイルの読み込みについて【備忘録】

CSVファイルに保存されたデータを読み込む方法を備忘録としてまとめる．
使用言語はPython．

本記事中で例示するために使用したコードとデータは，<a href="https://github.com/SiganAI-kun/load_csv">ここ</a>からダウンロード可能．

<h1>方法１：pandasの使用</h1>

個人的に一番使っている方法．
pandasの[`read_csv`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html)関数を使用．
CSVに保存されているデータをデータフレーム（表形式）で読み込むことが可能．
引数`filepath_or_buffer`にCSVファイルのパス（本記事では変数`path`）を渡す．

<h2>インストール方法</h2>

```terminal:terminal
pip install pandas
```

<h3>実際の使用例</h3>

```python:pandas_test.py
import pandas as pd
path = "test.csv"
data = pd.read_csv(path)

print(data)
#     A   B   C   D
# 0   0   1   2   3
# 1  10  11  12  13
# 2  20  21  22  23
# 3  30  31  32  33
```

<h2>個人的によく使う引数</h2>

*<h3>header</h3>*

カラム（列）名として使用する行を定義する．
`0`や`None`とすることが多い．

`0`：CSVファイルの第１行をカラム名とする（デフォルト）
`None`：カラム名をCSVファイルから取得しない
このとき，もっとも左の列から順に0列，1列，2列…となる．
基本的に，データラベルの付いていない状態でデータが保存されているときに使う．

```python:pandas_test.py
data2 = pd.read_csv(path,header=0)
print(data2)
#     A   B   C   D
# 0   0   1   2   3
# 1  10  11  12  13
# 2  20  21  22  23
# 3  30  31  32  33

data3 = pd.read_csv(path, header=None)
print(data3)
#     0   1   2   3
# 0   A   B   C   D
# 1   0   1   2   3
# 2  10  11  12  13
# 3  20  21  22  23
# 4  30  31  32  33
```

*<h3>names</h3>*

カラム名をCSVファイルの外部から定義する．
引数にはリストやタプルを渡す．
`header=None`と併用することが多い．

```python:pandas_test.py
data4 = pd.read_csv(path, header=None, names=('a', 'b', 'c', 'd'))
print(data4)
#     a   b   c   d
# 0   A   B   C   D
# 1   0   1   2   3
# 2  10  11  12  13
# 3  20  21  22  23
# 4  30  31  32  33
```

*<h3>index_col</h3>*

インデックス名として使用する列を定義する（引数を定義しなければ0からの連番が要素の１行目からつけられる）
`0`：１番左の列を`index`として使用

```python:pandas_test.py
data5 = pd.read_csv(path, index_col=0)
print(data5)
#      B   C   D
# A    
# 0    1   2   3
# 10  11  12  13
# 20  21  22  23
# 30  31  32  33
```

*<h3>usecols</h3>*

指定した列のみを読み込む
引数にはリストを渡す

```python:pandas_test.py
data6 = pd.read_csv(path, usecols=[0, 2])
print(data6)
#     A   C
# 0   0   2
# 1  10  12
# 2  20  22
# 3  30  32

data6_2 = pd.read_csv(path, usecols=[1])
print(data6_2)
#     B
# 0   1
# 1  11
# 2  21
# 3  31
```

特定の1列だけを読み込む場合でもリストを渡す必要があるため注意．


<h1>方法２：numpyの使用</h1>

`numpy`の[`loadtxt`](https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html)関数を使用する．
CSVに保存されているデータを`ndarray`(配列形式)で読み込むことが可能．
引数`fname`にCSVファイルのパス（本記事では変数`path`）を渡す．

<h2>インストール方法</h2>

```terminal:terminal
pip install numpy
```

<h3>実際の使用例</h3>

```python:numpy_test.py
import numpy as np
path = "test2.csv"
data = np.loadtxt(path, delimiter=',')

print(data)
#[[ 0.  1.  2.  3.]
# [10. 11. 12. 13.]
# [20. 21. 22. 23.]
# [30. 31. 32. 33.]]
```

<h2>個人的によく使う引数</h2>

*<h3>delimiter</h3>*

CSVを読み込むときは`','`で指定しないと読み込めない．（デフォルトは`' '`（スペース））

```python:numpy_test.py
data2 = np.loadtxt(path)

print(data)
# ValueError: could not convert string '00,01,02,03' to float64 at row 0, column 1.
```

`delimiter`を指定しないと，`float`型で読み込めないため，上のようなエラーが発生するため要注意．

<h1>方法３：CSVモジュールの使用</h1>

個人的にはpandasの方が使い勝手が良いため，ほぼ出番はない．
しかしデータの性質上，**（欠損以外の要因で）行ごとの要素数が変動してしまうような場合**には，上記の2点では正確に読み込めない場合があるため，CSVモジュールを使うほかない．

```python:csv_test.py
import csv

path = "test.csv"
with open(path) as f:
	data = f.read()
```

`read`関数を使うとデータを文字列として読み込むことが可能．
後々の処理において，`ndarray`やリストの方が都合が良い場合は以下のコードでリスト化する．
`reader`関数による返り値をそのまま使うことはできないので要注意．

```python:csv_test.py
data2 = []
with open(path) as f:
	rows = csv.reader(f)
	print(rows)
	#<_csv.reader object at 0x0000017463001B40>
	for row in rows:
		data2.append(row)

print(data2)
#[['A', 'B', 'C', 'D'], ['00', '01', '02', '03'], ['10', '11', '12', '13'], ['20', '21', '22', '23'], ['30', '31', '32', '33']]
```

このコードでは，変数`data2`にCSVに記述されたデータをリスト型で格納できたことになる．

ちなみに，各要素は文字列で読み込まれるため，整数値や小数値で読み込みたい場合にはもう一工夫必要である．
全ての要素を整数で読み込む際の例を以下に示す．

```python:csv_test.py
path = "test2.csv"
data3 = []
with open(path) as f:
	rows = csv.reader(f)
	for row in rows:
		data3.append([])
		for i in range(len(row)):
			data3[-1].append(int(row[i]))

print(data3)
#[[0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23], [30, 31, 32, 33]]
```