【機械学習】pandasでCSV読み込み
※ 2020/02/16にQrunchで書いた記事を移行しました。
Pyhtonで機械学習を行うとき、入力データをCSVファイルから取得することがあります。
Pythonで機械学習と言えばnumpyが欠かせませんが、CSVファイルの読み込みはpandasで行うと大変便利です。数行のコードで大抵のことは出来てしまいます。
pandaで読み込んだデータをnumpy形式(ndarray)に変換して、機械学習用のライブラリに渡してあげればOKです。
公式のリファレンスを参考に、色々なCSVファイルを読み込んでみました。
- read_csvで読み込み
- タブ区切りのファイル読み込み
- タイトル行が無い場合
- タイトル行が複数の場合
- 任意の列名を付ける
- インデックス列を指定する
- インデックス列を複数指定する
- 指定した列のみを読み込む
- スペースを無視したい場合
- 指定した行を飛ばす
- na_values
- 日付をdatatime型として読み込む
- データ型を指定する
- より詳しいことを知りたい方は
read_csvで読み込み
A,B,C,D,E 0,1,2,3,4 5,6,7,8,9 10,11,12,13,14
上記のようなCSVファイルを読み込む場合、以下のように書くと、
# coding: utf-8 import pandas as pd df = pd.read_csv('foo.csv') print(df) # A B C D E # 0 0 1 2 3 4 # 1 5 6 7 8 9 # 2 10 11 12 13 14
デフォルトでは、先頭行をタイトル行(A,B,C,D,E)として読み込みます。 各行のインデックス(0,1,2)は自動で付与されます。
タブ区切りのファイル読み込み
A___B___C___D___E 0___1___2___3___4 5___6___7___8___9 10___11___12___13___14
タブ区切りのファイルを読み込む場合はsep='\t'
を指定します。
df = pd.read_csv('foo.csv', sep='\t') print(df) # A B C D E # 0 0 1 2 3 4 # 1 5 6 7 8 9 # 2 10 11 12 13 14
カンマとタブ区切りに限らず、sep
で区切り文字を指定できます。
タイトル行が無い場合
0,1,2,3,4 5,6,7,8,9 10,11,12,13,14
タイトル行の無いCSVファイルを読み込む場合はheader=None
を指定します。
df = pd.read_csv('foo.csv', header=None) print(df) # 0 1 2 3 4 # 0 0 1 2 3 4 # 1 5 6 7 8 9 # 2 10 11 12 13 14
列の名前は自動で付与してくれます。
タイトル行が複数の場合
A,A,B,B,C a,b,a,b,a 0,1,2,3,4 5,6,7,8,9 10,11,12,13,14
タイトル行が複数ある場合はheader=[0,1]
のように、リストで行番号を指定します。
df = pd.read_csv('foo.csv', header=[0,1]) print(df) # A B C # a b a b a # 0 0 1 2 3 4 # 1 5 6 7 8 9 # 2 10 11 12 13 14
任意の列名を付ける
0,1,2,3,4 5,6,7,8,9 10,11,12,13,14
タイトル行を自分で付ける場合はnames
に名称を指定します。
df = pd.read_csv('foo.csv', names=['a','b','c','d','e']) print(df) # a b c d e # 0 0 1 2 3 4 # 1 5 6 7 8 9 # 2 10 11 12 13 14
インデックス列を指定する
,A,B,C,D,E i,0,1,2,3,4 j,5,6,7,8,9 k,0,1,2,3,4
インデックス列を指定する場合はindex_col
に整数を指定します。
df = pd.read_csv('foo.csv', index_col=0) print(df) # A B C D E # i 0 1 2 3 4 # j 5 6 7 8 9 # k 0 1 2 3 4
列名を指定することも出来ます。以下はA列を指定した例です。
df = pd.read_csv('foo.csv', index_col='A') print(df) # Unnamed: 0 B C D E # A # 0 i 1 2 3 4 # 5 j 6 7 8 9 # 0 k 1 2 3 4
インデックス列を複数指定する
,,A,B,C,D,E i,k,0,1,2,3,4 i,l,5,6,7,8,9 j,m,0,1,2,3,4
インデックス列を複数指定する場合はindex_col=[0,1]
のように、リストで列番号を指定します。
df = pd.read_csv('foo.csv', index_col=[0,1]) print(df) # A B C D E # i k 0 1 2 3 4 # l 5 6 7 8 9 # j m 0 1 2 3 4
列名を複数指定する場合も同様に、リストで指定します。
df = pd.read_csv('foo.csv', index_col=['A','B']) print(df) # Unnamed: 0 Unnamed: 1 C D E # A B # 0 1 i k 2 3 4 # 5 6 i l 7 8 9 # 0 1 j m 2 3 4
名称が付いていない列はUnnamed: 〜
が自動で付与されます。
指定した列のみを読み込む
,A,B,C,D,E i,0,1,2,3,4 j,5,6,7,8,9 k,0,1,2,3,4
指定した列のみを読み込む場合はusecols[0,1]
のようにリスト形式で指定します。
df = pd.read_csv('foo.csv', usecols=[1,2]) print(df) # A B # 0 0 1 # 1 5 6 # 2 0 1
列名を指定することも可能です。
df = pd.read_csv('foo.csv', usecols=['A','E']) print(df) # A E # 0 0 4 # 1 5 9 # 2 0 4
また、ラムダ式で条件を設定し、条件に合致する列のみを読み込むことも出来ます。
df = pd.read_csv('foo.csv', usecols=lambda s: s < 'C') print(df) # A B # 0 0 1 # 1 5 6 # 2 0 1
スペースを無視したい場合
no, name, age 1, Taro, 15 2, Jiro, 10 3, Saburo, 5
上記のように、区切り文字の後ろに半角スペースが含まれる場合、半角スペースも一緒に読み込まれてしまいます。数値の場合は問題ないのですが、列名や文字列データに余分なスペースが含まれてしまいます。
df = pd.read_csv('foo.csv') print(df) # no name age # 0 1 Taro 15 # 1 2 Jiro 10 # 2 3 Saburo 5 print(df.columns) # Index(['no', ' name', ' age'], dtype='object')
半角スペースを飛ばしたい場合はskipinitialspace=True
を指定します。
df = pd.read_csv('foo.csv', skipinitialspace=True) print(df) # no name age # 0 1 Taro 15 # 1 2 Jiro 10 # 2 3 Saburo 5 print(df.columns) # Index(['no', 'name', 'age'], dtype='object')
指定した行を飛ばす
foo.csv A,B,C,D,E 0,1,2,3,4 5,6,7,8,9 10,11,12,13,14
上記のように1,2行目は読込不要の場合はskiprows=[0,1]
のように、リストで読込不要な行の番号を指定します。
df = pd.read_csv('foo.csv', skiprows=[0,1]) print(df) # A B C D E # 0 0 1 2 3 4 # 1 5 6 7 8 9 # 2 10 11 12 13 14
na_values
A,B,C,D,E 0,1,2,3,NG 5,6,,,9 -,-,12,13,14
空白は、欠損=NaN(numpy.nan)として読み込まれます。
df = pd.read_csv('foo.csv') print(df) # A B C D E # 0 0 1 2.0 3.0 NG # 1 5 6 NaN NaN 9 # 2 - - 12.0 13.0 14
空白以外にも欠損=NaNに指定したいデータがある場合はna_values
で指定します。
df = pd.read_csv('foo.csv', na_values=['-','NG']) print(df) # A B C D E # 0 0.0 1.0 2.0 3.0 NaN # 1 5.0 6.0 NaN NaN 9.0 # 2 NaN NaN 12.0 13.0 14.0
日付をdatatime型として読み込む
date,Temp.,Humidity 2017/1/1,-1.1,10 2017/1/2,-2.2,20 2017/1/3,-3.3,30
日付データはデフォルトでは、object型として読み込まれます。
df = pd.read_csv('foo.csv') print(df) # date Temp. Humidity # 0 2017/1/1 -1.1 10 # 1 2017/1/2 -2.2 20 # 2 2017/1/3 -3.3 30 print(df.dtypes) # date object # Temp. float64 # Humidity int64 # dtype: object
日付として読み込みたい列をparse_dates
で指定します。
列番号で指定しても列名で指定しても動作します。
下記例ではparse_dates=['date']
をparse_dates=[0]
に変えても同じように動作します。
df = pd.read_csv('foo.csv', parse_dates=['date']) print(df) # date Temp. Humidity # 0 2017-01-01 -1.1 10 # 1 2017-01-02 -2.2 20 # 2 2017-01-03 -3.3 30 print(df.dtypes) # date datetime64[ns] # Temp. float64 # Humidity int64 # dtype: object
データ型を指定する
no,name,age,height 1,Taro,50,170 2,Sachiko,40,160 3,Masami,30,180
データ型を指定しない場合、自動でデータ型を判定してくれますが、それでは不都合な場合もあります。上記例では"height"は実数型(float)で扱ってほしいのですが整数型(int)と判定されます。
df = pd.read_csv('foo.csv') print(df) # no name age height # 0 1 Taro 50 170 # 1 2 Sachiko 40 160 # 2 3 Masami 30 180 print(df.dtypes) # no int64 # name object # age int64 # height int64 # dtype: object
データ型を指定したい場合にはdtype
で型を指定します。
np.int64
やnp.float64
は"Int64"
のように文字列で指定することも可能です。
import numpy as np df = pd.read_csv('foo.csv', dtype={'no': np.int64, 'name': object, 'age': np.int64, 'height': np.float64} ) print(df) # no name age height # 0 1 Taro 50 170.0 # 1 2 Sachiko 40 160.0 # 2 3 Masami 30 180.0 print(df.dtypes) # no int64 # name object # age int64 # height float64 # dtype: object
より詳しいことを知りたい方は
pandas公式のUser GuideやCookbookにより詳しく使い方が載っています。 IO tools (text, CSV, HDF5, …) — pandas 1.0.1 documentation< Cookbook — pandas 1.0.1 documentation