どこにでもいる30代SEの学習ブログ

主にプログラミング関連の学習内容。読んだ本の感想や株式投資についても書いてます。

【機械学習】pandasでCSV読み込み

f:id:predora005:20200920113519p:plain

※ 2020/02/16にQrunchで書いた記事を移行しました。

Pyhtonで機械学習を行うとき、入力データをCSVファイルから取得することがあります。

Python機械学習と言えばnumpyが欠かせませんが、CSVファイルの読み込みはpandasで行うと大変便利です。数行のコードで大抵のことは出来てしまいます。

pandaで読み込んだデータをnumpy形式(ndarray)に変換して、機械学習用のライブラリに渡してあげればOKです。

公式のリファレンスを参考に、色々なCSVファイルを読み込んでみました。

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.int64np.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