[解決!Python]CSVファイルから読み込みを行うには(NumPy編):解決!Python
NumPyが提供するloadtxt関数とgenfromtxt関数を使って、CSVファイルなどからデータを読み込む方法を紹介する。
import numpy as np
from pathlib import Path
# numpy.loadtxt関数
# 読み込むCSVファイルの内容を確認
filename = 'test0.csv'
print(Path(filename).read_text())
#0 1 2 # 数値が空白文字で区切られている
#3 4 5
#6 7 8
# loadtxt関数の基本的な使い方
myarray = np.loadtxt(filename) # デフォルトでは空白文字が区切り文字
print(myarray) # デフォルトでは読み込んだ値は浮動小数点数値となる
#[[0. 1. 2.]
# [3. 4. 5.]
# [6. 7. 8.]]
# データ型を指定
myarray = np.loadtxt(filename, dtype=int) # 全てのフィールドが整数と指定
print(myarray)
#[[0 1 2]
# [3 4 5]
# [6 7 8]]
# 読み込むCSVファイルの内容を確認
filename = 'test1.csv'
print(Path(filename).read_text())
#0,1,2 # 数値がカンマで区切られている
#3,4,5
#6,7,8
# 区切り文字を指定
myarray = np.loadtxt(filename, delimiter=',') # 区切り文字としてカンマを指定
print(myarray)
#[[0. 1. 2.]
# [3. 4. 5.]
# [6. 7. 8.]]
myarray = np.loadtxt(filename) # ValueError:デフォルトは空白文字が区切り文字
# 読み込むCSVファイルの内容を確認
filename = 'test2.csv'
print(Path(filename).read_text())
#col1 col2 col3 # ヘッダーあり。数値が空白文字で区切られている
#0 1 2
#3 4 5
#6 7 8
# 先頭行を読み飛ばす
myarray = np.loadtxt(filename, skiprows=1) # 先頭の1行を読み飛ばす
print(myarray)
#[[0. 1. 2.]
# [3. 4. 5.]
# [6. 7. 8.]]
# 読み込むCSVファイルの内容を確認
filename = 'test3.csv'
with open(filename, encoding='utf8') as f:
print(f.read())
#一色 25 170 # 文字列/数値/数値が空白文字で区切られている
#かわさき 80 168
# 読み込む列を指定する
myarray = np.loadtxt(filename, usecols=[1, 2], encoding='utf8')
print(myarray)
#[[ 25. 170.]
# [ 80. 168.]]
# 列ごとに内容を取り出す(転置)
ages, heights = np.loadtxt(filename, unpack=True, usecols=[1, 2], encoding='utf8')
print(ages) # [25. 80.]
print(heights) # [170. 168.]
# numpy.genfromtxt関数
# 読み込むCSVファイルの内容を確認
filename = 'test4.csv'
with open(filename, encoding='utf8') as f:
print(f.read())
#name age height # ヘッダーあり。文字列/数値/数値が空白文字で区切られている
#一色 25 170
#かわさき 80 168
# 基本的な読み込み
myarray = np.genfromtxt(filename, encoding='utf8')
print(myarray)
#[[ nan nan nan] # 数値以外はnanとされている
# [ nan 25. 170.]
# [ nan 80. 168.]]
print(myarray.dtype) # float64
# 各フィールドの値からデータ型を判定
myarray = np.genfromtxt(filename, encoding='utf8', dtype=None)
print(myarray)
#[['name' 'age' 'height']
# ['一色' '25' '170']
# ['かわさき' '80' '168']]
print(myarray.dtype) # <U6(全てが6文字以下の文字列と判定された)
# 1行目をヘッダーとして扱い、各列のデータ型を明示的に指定
myarray = np.genfromtxt(filename, names=True, dtype='U4,f,f', encoding='utf8')
print(myarray) # [('一色', 25., 170.) ('かわさき', 80., 168.)]
print(myarray.dtype) # [('name', '<U4'), ('age', '<f4'), ('height', '<f4')]
# 読み込むCSVファイルの内容を確認
filename = 'test5.csv'
with open(filename, encoding='utf8') as f:
print(f.read())
#0,,2 # 各行に欠損している値がある
#,4,5
#6,,8
# 欠損値をnanで埋める
myarray = np.genfromtxt(filename, delimiter=',', encoding='utf8')
print(myarray)
#[[ 0. nan 2.] # 欠損している部分の値はnanになる
# [nan 4. 5.]
# [ 6. nan 8.]]
myarray = np.loadtxt(filename, delimiter=',', encoding='utf8') # ValueError
# 欠損値を埋める値を指定する
myarray = np.genfromtxt(filename, delimiter=',', filling_values=-1, encoding='utf8')
print(myarray)
#[[ 0. -1. 2.]
# [-1. 4. 5.]
# [ 6. -1. 8.]]
NumPyにはloadtxt関数とgenfromtxt関数があり、これらを使うことでCSVファイル(あるいは任意の文字を区切り文字としてフィールドを分割する形式のファイル)から読み込みを行える。
以下では、それら2つの関数の基本的な使い方を紹介する。なお、本稿ではCSVファイル(または空白文字を区切り文字とするファイル)の内容を表示してから、「このときにはこんな感じで関数を呼び出す」例を示すことにする。
numpy.loadtxt関数
numpy.loadtxt関数(以下、loadtxt関数)は何らかの文字を区切り文字として、「数値」が並べられているファイルの内容を読み込んで、それをNumPyの配列(numpy.ndarray)として返送する。
以下にnumpy.loadtxt関数の構文を示す。ただし、指定可能なパラメーターはこれら以外にも多数あるので、詳細については「numpy.loadtxt」を参照されたい。
numpy.loadtxt(fname, dtype, delimiter, skiprows, usecols, unpack)
上に挙げた指定可能なパラメーターはおおよそ次のような意味を持つ。また、読み込むファイルには各行に同じ数のデータが含まれている必要がある。ファイルのエンコーディングを指定するためのencodingパラメーターもあるが、これについては詳しくは触れない。
- fname:読み込むファイルの名前(またはジェネレータ)。必須
- dtype:返送する配列のデータ型(CSVファイルにはここで指定されたデータ型の値が記述されているものと見なされる)。省略可。デフォルト値はfloat
- delimiter:区切り文字の指定。省略可。デフォルト値は空白文字
- skiprows:先頭から読み飛ばす行数。省略可。デフォルト値は「0」(読み飛ばさない)
- usecols:読み込みを行う列の指定(先頭列が0、次の列が1、……、となる)。整数値、もしくは整数値を要素とするシーケンス(リストなど)。省略可。デフォルト値はNone(全ての列が読み込まれる)
- unpack:Trueなら読み込んだ配列を転置したものが返される。省略可。デフォルト値はFalse(読み込んだ配列がそのまま返される)
以下は最も基本的な呼び出しの例だ。
filename = 'test0.csv'
print(Path(filename).read_text())
#0 1 2 # 数値が空白文字で区切られている
#3 4 5
#6 7 8
myarray = np.loadtxt(filename) # デフォルトでは空白文字が区切り文字
print(myarray) # デフォルトでは読み込んだ値は浮動小数点数値となる
#[[0. 1. 2.]
# [3. 4. 5.]
# [6. 7. 8.]]
print(type(myarray)) # <class 'numpy.ndarray'>
loadtxt関数を呼び出す前に、読み込むファイルの内容を確認すると、各行には3つの数値が空白文字で区切られて並べられていることが分かる。上で述べたように、loadtxt関数はdelimiterパラメーターに区切り文字を指定しない限り、空白文字が区切り文字として扱われるので、このようにしてある。
その後、読み込むファイルの名前だけを指定してloadtxt関数を指定している。その戻り値は上に示した通り、浮動小数点数値を3つ含んだNumPyの配列(numpy.ndarray)となっている。また、「0.」「1.」のように読み込んだ値はデフォルトで浮動小数点数値となる点にも注意しよう。
データ型を指定
ファイルに格納されているデータの型を指定するにはdtypeパラメーターを使用する。以下の例では「dtype=int」として整数値が含まれていることを示している。
myarray = np.loadtxt(filename, dtype=int) # 全てのフィールドが整数と指定
print(myarray)
#[[0 1 2]
# [3 4 5]
# [6 7 8]]
区切り文字を指定
次に区切り文字を指定する方法を見る。上と同様に、読み込むファイルの内容を確認すると、今度は次のようにカンマ区切りとなっている。
filename = 'test1.csv'
print(Path(filename).read_text())
#0,1,2 # 数値がカンマで区切られている
#3,4,5
#6,7,8
区切り文字を指定するには、delimiterパラメーターを使用する。以下に例を示す。
myarray = np.loadtxt(filename, delimiter=',') # 区切り文字としてカンマを指定
print(myarray)
#[[0. 1. 2.]
# [3. 4. 5.]
# [6. 7. 8.]]
結果は先ほどと同様である。なお、カンマを区切り文字として使っているファイルに対して、delimiterパラメーターを指定せずにloadtxt関数を呼び出すと以下のように例外が発生する。
myarray = np.loadtxt(filename) # ValueError:デフォルトは空白文字が区切り文字
先頭行を読み飛ばす
以下のようにヘッダー行がある場合に、その行を読み飛ばすにはskiprowsパラメーターに読み飛ばす行数を指定すればよい。
filename = 'test2.csv'
print(Path(filename).read_text())
#col1 col2 col3 # ヘッダーあり。数値が空白文字で区切られている
#0 1 2
#3 4 5
#6 7 8
以下に例を示す。この場合は、読み飛ばす行は1行でよいので、「skiprows=1」としている。
myarray = np.loadtxt(filename, skiprows=1) # 先頭の1行を読み飛ばす
print(myarray)
#[[0. 1. 2.]
# [3. 4. 5.]
# [6. 7. 8.]]
読み込む列を指定する
今度は次のように、文字列と数値が混在するCSVファイルから読み込んでみる。
filename = 'test3.csv'
with open(filename, encoding='utf8') as f:
print(f.read())
#一色 25 170 # 文字列/数値/数値が空白文字で区切られている
#かわさき 80 168
データ型を指定せずに読み込もうとすると次のように例外が発生する。
myarray = np.loadtxt(filename, encoding='utf8') # ValueError
しかし、データ型をstrに指定してもあまり意味はないだろう。loadtxt関数では、特定のフィールドが特定の型という指定はできず、全てのデータがある型でなければならない。
myarray = np.loadtxt(filename, dtype=str, encoding='utf8')
print(myarray)
#[['一色' '25' '170']
# ['かわさき' '80' '168']]
このようなときに、数値のみを含んだフィールドだけを読み込みたいのであれば、usecolsパラメーターに読み込みたい列を指定する(先頭列が0、次の列が1、……のようになる)。以下は第1列と第2列の内容だけを読み込むコードだ。
myarray = np.loadtxt(filename, usecols=[1, 2], encoding='utf8')
print(myarray)
#[[ 25. 170.]
# [ 80. 168.]]
このようなときには、以下で紹介するgenfromtxt関数を使うか、別稿で取り上げる予定のpandasを使うのがよいだろう。
列ごとに内容を取り出す(転置)
先頭列の内容からなる配列、次の列の内容からなる配列などがほしいときには、unpackパラメーターにTrueを指定するとよい。以下に例を示す。
ages, heights = np.loadtxt(filename, unpack=True, usecols=[1, 2], encoding='utf8')
print(ages) # [25. 80.]
print(heights) # [170. 168.]
numpy.genfromtxt関数
loadtxt関数はシンプルな(全てのデータが同一の型を持つ)場合には便利に使えるかもしれないが、numpy.genfromtxt関数(以下、genfromtxt関数)はもっと構造的なデータを扱える。また、読み込むファイルに欠損値が含まれている場合に、その値を自動でセットすることもできる(デフォルトではnan値)。ただし、より高度な処理を行うのであれば、pandasを使う方がよいだろう。
以下にgenfromtxt関数の構文を示す。loadtxt関数と同じく、パラメーターは本稿で紹介するものだけを示しているので、詳細については「numpy.genfromtxt」を参照されたい。
numpy.genfromtxt(fname, dtype, names, filling_values)
パラメーターは以下の通り。
- fname:読み込みを行うファイルの名前。必須。fnameにはファイル名以外も指定可能だが、本稿では取り上げない
- dtype:返送する配列のデータ型。省略可。省略した場合のデータ型はfloat
- names:Trueの場合、CSVファイルの先頭行から各列の名前が決定される。文字列を要素とするリスト、列名をカンマで区切った文字列を渡すことも可能。省略可。省略した場合はNoneを指定したものとされる(この場合は、dtypeパラメーターで列名が指定されている場合には、それが使用される)
- filling_values:欠損値があった場合に、デフォルト値として使われる値を指定。省略可。省略時はNoneが指定されたものとして扱われる(欠損している箇所にはnanがセットされる)
Copyright© Digital Advantage Corp. All Rights Reserved.