CSV, TSVファイルの読み込んでDataFrameを作成

CSV, TSVファイルからデータを読み込んで、DataFrameを作成する方法についてまとめます。
今回は以下の関数を紹介します。

pandas.read_csv
 CSV(Comma-Separated Value)ファイルを読み込みます。
pandas.read_table
 TSV(Tab-Separated Values)ファイルを読み込みます。

CSV/TSVファイルの違い

ご存じの方は読み飛ばしてください。 とりあえずWikipediaより引用します。

Comma-Separated Values

comma-separated values(略称:CSV)は、テキストデータをいくつかのフィールド(項目)に分け、区切り文字であるカンマ「,」で区切ったデータ形式。拡張子は .csv、MIMEタイプは text/csv。

Tab-Separated Values

Tab-Separated Values (TSV) は、データベースにおける表や表計算データなど、表形式でデータを格納するためのシンプルなテキスト形式のデータ形式であり[1]、データベース間で情報を交換する方法の1つである[2]。
TSV形式における各レコードは、テキストファイルの1行である。レコードの各フィールド値は、タブ文字で区切られる。すなわち、TSV形式はDelimiter-Separated Values(英語版)(区切り文字区切り形式)の一種である。タブ区切り形式ともいう。

要するに区切り文字が「, (コンマ)」か「\t(タブ)」かの違いだけのようです。まとめてcharacter-separated valuesと呼ぶこともあるようです。

コンマの代わりに別の文字を区切りに使ったフォーマットもあり、まとめて character-separated values、delimiter-separated values と呼ぶ。
代表的なものに以下のようなものがある。
・タブ - tab-separated values (TSV) - MIME type は text/tab-separated-values
・スペース - space-separated values (SSV)
・セミコロン - semicolon-separated values (SSV)

デファクトスタンダードとしてCSVファイルが使われることが多いようです。僕もCSVファイルをよく見る印象です。Excelファイルからエクスポートするときにもデフォルトで選択できるのはCSVファイルのほうです。(TSV形式でのエクスポートもやればできます。)

ただしCSVファイルには以下のような問題があります。

・データに「,(コンマ)」が含まれていると、意図した通りに扱えない。
・データと区切り文字を区別するために、データ全体を「"(ダブルクォーテーション)」で囲む必要があります。その場合、データ内に「"(ダブルクォーテーション)」が含まれると、意図した通りに扱えない。
・「"(ダブルクォーテーション)」をエスケープするために、更に「"(ダブルクォーテーション)」で囲むことになるので、読みづらくなる。
・さらに上記の対応はソフトウェアによって解釈が異なり、区切り方が変わることがある。

以上のような事情から、数値情報だけのファイル(0, 1, …, 9)の場合にはCSVファイルでも良いのですが、文字情報を使ったファイル(0.…, 9, コンマ, ダブルクォーテーション, 文章など)の場合にはTSVファイルを選んだほうが良さそうです。もちろんこのときデータに「\t(タブ)」は含まれないほうが良いです。

read_csv/read_tableメソッドと、その違い

read_csv/read_tableメソッドは区切り文字が違うだけで他は一緒らしく、内部のコードも共通になっているらしいです。その区切り文字も引数で変更することができます。例えば、read_csvメソッドの区切り文字の引数に「\t(タブ)」を指定したら、TSVファイルを扱うことができます。  

そのため以降ではread_csvメソッドだけで説明しますが、read_tableメソッドでも同様の使い方になります。

今回も引数とその意味を紹介しますが、read_csv/read_tableの引数は数がとても多いです。それらを駆使することで詳細に動きを決めることができるのですが、今回は数を絞って紹介します。

今回は以下のような引数を使用します。

・filepath_or_buffer
 型: str
 読み込むファイルのパスを指定します。
 指定が必須な引数はこれだけです。これ以降の引数は必ずしも指定する必要はありません。
・sep
 型: str
 区切り文字を指定します。
・delimiter
 型: str
 sepと同じ意味を持ちます。どちらかだけを指定していればいいです。
・header
 型: int
 headerとして扱う行番号を指定します。
・names
 型: リスト
 ヘッダとするラベルをリスト形式で指定します。
・index_col
 型: int, str, リスト, False
 indexとする列を指定します。int型で指定したときは列番号として、str型で指定したときは列ラベルとして扱われ、該当する列がindexとして扱われます。
 Falseを指定すると、ファイル内のデータをindexとして扱うことはなく、0からの連番を割り当てます。
・usecols
 型: リスト
 読み込みたい列を指定します。
・skiprows
 型: リスト
 読み飛ばしたい行を指定します。
・skipfooter
 型: int
 ファイル末尾をスキップするときに指定します。読み飛ばす行数を指定します。
・nrows
 型: int
 指定した最初の数行だけを読み込みます。
・na_values
 型: 数値型, str, リスト, 辞書
 追加で欠損値(NaN)として扱うデータを指定します。N/A, NULLなどはデフォルトで欠損値として扱われます。
 デフォルトで欠損値して扱われるデータの一覧は公式リファレンスにあります。
・encoding
 型: str
 ファイルの文字コードを指定します。デフォルトは"utf-8"です。
 List of Python standard encodingsも参考にしてください。

CSV/TSVファイルの読み込み

最低限、filepath_or_bufferにファイルパスを指定する必要があります。read_csvメソッドの場合、デフォルトではcsvファイルを読み込みます。
sep, delimiterに区切り文字を指定することで、tsvファイルなどを読み込むことができるようになります。

今回は以下の2つのファイルを使用します。

sample1.csv

1,2,3,4,5
11,12,13,14,15
21,22,23,24,25
31,32,33,34,35

sample1.tsv

1   2   3   4   5
11  12  13  14  15
21  22  23  24  25
31  32  33  34  35

※sample.tsvの空白はすべて\t(タブ)となっています。

CSVファイルを読み込みます。

import pandas

# デフォルトではコンマ区切りのファイルを読み込みます。
print(pandas.read_csv("sample1.csv"))

#     1   2   3   4   5
# 0  11  12  13  14  15
# 1  21  22  23  24  25
# 2  31  32  33  34  35

区切り文字としてタブを指定します。TSVファイルを読み込みます。

print(pandas.read_csv("sample1.tsv", sep="\t"))

#     1   2   3   4   5
# 0  11  12  13  14  15
# 1  21  22  23  24  25
# 2  31  32  33  34  35

区切り文字として、sepとdelimiterの両方を指定した場合、delimiterが優先されます。
この例では、TSVファイルに対して、区切り文字をコンマで指定していることになるため、意図した通りに読み込めていません。

print(pandas.read_csv("sample1.tsv", sep="\t", delimiter=","))

#         1\t2\t3\t4\t5
# 0  11\t12\t13\t14\t15
# 1  21\t22\t23\t24\t25
# 2  31\t32\t33\t34\t35

headerの扱い

引数headerに何も指定しなければ、1行目がheaderとして扱われます。

df = pandas.read_csv("sample1.csv")
print(df)
print()
print(df.columns)

#     1   2   3   4   5
# 0  11  12  13  14  15
# 1  21  22  23  24  25
# 2  31  32  33  34  35
# 
# Index(['1', ' 2', ' 3', ' 4', ' 5'], dtype='object')

header=Noneとすると、headerがないファイルとして読み込まれます。その際、headerとして0からの連番が割り当てられます。

df = pandas.read_csv("sample1.csv", header=None)
print(df)
print()
print(df.columns)

#     0   1   2   3   4
# 0   1   2   3   4   5
# 1  11  12  13  14  15
# 2  21  22  23  24  25
# 3  31  32  33  34  35
# 
# Int64Index([0, 1, 2, 3, 4], dtype='int64')

headerに0始まりの数値を入れることで、ヘッダとして扱う0始まりの行を指定します。ヘッダより上の行は無視されます。

df = pandas.read_csv("sample1.csv", header=1)
print(df)
print()
print(df.columns)

#    11   12   13   14   15
# 0  21   22   23   24   25
# 1  31   32   33   34   35
# 
# Index(['11', ' 12', ' 13', ' 14', ' 15'], dtype='object')

namesにリストを指定することで、ヘッダを指定することができます。

df = pandas.read_csv("sample1.csv", names=["col1", "col2", "col3", "col4", "col5"])
print(df)
print()
print(df.columns)

#    col1  col2  col3  col4  col5
# 0     1     2     3     4     5
# 1    11    12    13    14    15
# 2    21    22    23    24    25
# 3    31    32    33    34    35
# 
# Index(['col1', 'col2', 'col3', 'col4', 'col5'], dtype='object')

indexの扱い

何も指定しなければ、indexとして0始まりの連番が割り当てられます。
index_colに0始まりの数値を入れることで、indexとして扱う0始まりの列を指定します。指定された列以外がデータとして扱われます。

# indexとして0始まりの連番が割り当てられます。
df = pandas.read_csv("sample1.csv")
print(df)
print()
print(df.index)

print("---------------------------")
# 1番目の列がindexとして扱われます。
# 0, 2, 3, 4番目の列はそのままデータになります。
df = pandas.read_csv("sample1.csv", index_col=1)
print(df)
print()
print(df.index)

#     1   2   3   4   5
# 0  11  12  13  14  15
# 1  21  22  23  24  25
# 2  31  32  33  34  35
# 
# RangeIndex(start=0, stop=3, step=1)
# ---------------------------
#      1   3   4   5
#  2                
# 12  11  13  14  15
# 22  21  23  24  25
# 32  31  33  34  35
# 
# Int64Index([12, 22, 32], dtype='int64', name=' 2')

列を指定して読み込み

usecolsにリストを指定すると、データとして読み込む列を指定することができます。

# 列番号で指定しています。
print(pandas.read_csv("sample1.csv", usecols=[2, 4]))

#     3   5
# 0  13  15
# 1  23  25
# 2  33  35

列番号ではなく、列名で指定することもできます。

print(pandas.read_csv("sample1.csv", usecols=["1", "3"]))

#     1   3
# 0  11  13
# 1  21  23
# 2  31  33

ラムダ式を使って指定することもできます。スキップする列を指定するときに利用することができます。

print(pandas.read_csv("sample1.csv", usecols=lambda x: x not in ["1", "3"]))

#     2   4   5
# 0  12  14  15
# 1  22  24  25
# 2  32  34  35

行を除外して読み込み

skiprowsに数値を指定することで、先頭から指定された行数分だけスキップして読み込みます。
このときスキップして読み込んだ後に、先頭の行がヘッダとして扱われることに注意してください。

print(pandas.read_csv("sample1.csv"))
print("-----------------------")
print(pandas.read_csv("sample1.csv", skiprows=2))
print("-----------------------")
print(pandas.read_csv("sample1.csv", skiprows=1))

#     1   2   3   4   5
# 0  11  12  13  14  15
# 1  21  22  23  24  25
# 2  31  32  33  34  35
# -----------------------
#    21  22  23  24  25
# 0  31  32  33  34  35
# -----------------------
#    11  12  13  14  15
# 0  21  22  23  24  25
# 1  31  32  33  34  35

skiprowsに数値ではなくリストを指定すると、指定された行番号がスキップされます。

print(pandas.read_csv("sample1.csv"))
print("-----------------------")
print(pandas.read_csv("sample1.csv", skiprows=[2]))

#     1   2   3   4   5
# 0  11  12  13  14  15
# 1  21  22  23  24  25
# 2  31  32  33  34  35
# -----------------------
#     1   2   3   4   5
# 0  11  12  13  14  15
# 1  31  32  33  34  35

skiprowsにもラムダ式を指定することができます。読み込む行を指定するときに利用することができます。

print(pandas.read_csv("sample1.csv", skiprows=lambda x: x not in [2, 3]))

#    21  22  23  24  25
# 0  31  32  33  34  35

skipfooterに数値を指定すると、ファイル末尾から読み込まない行数を指定することができます。
このとき、engine="python"と指定しておかないと警告が出ます。

print(pandas.read_csv("sample1.csv", skipfooter=2, engine="python"))

#     1   2   3   4   5
# 0  11  12  13  14  15

nrowsに数値を指定すると、先頭から指定した行数分だけ読み込みます。
このときheaderを読み込んだ後で、行数を数えるようです。

print(pandas.read_csv("sample1.csv", nrows=1))

#     1   2   3   4   5
# 0  11  12  13  14  15

欠損値として扱う値を指定する

na_valuesに値を指定することで、欠損値として扱う値を指定することができます。

print(pandas.read_csv("sample1.csv", na_values=13))

#     1   2     3   4   5
# 0  11  12   NaN  14  15
# 1  21  22  23.0  24  25
# 2  31  32  33.0  34  35

文字コードの指定

日本語が入ったファイルを扱うときは、encodingに文字コードを指定する必要があります。
次の例では以下のようなファイルを扱います。

sample2.csv

a,b,c,d
1,2,3,あ
12,13,14,い
ab,bc,cd,う
23,24,25,え

日本語が含まれたファイルを文字コード指定せずに(encoding='utf-8'として)読み込もうとすると、エラーとなります。


# print(pandas.read_csv("sample2.csv"))

# UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 0: invalid start byte

print(pandas.read_csv("sample2.csv", encoding="shift_jis"))

#     a   b   c  d
# 0   1   2   3  あ
# 1  12  13  14  い
# 2  ab  bc  cd  う
# 3  23  24  25  え

まとめ

今回はCSV, TSVファイルからデータを読み込んで、DataFrameを作成する方法をまとめました。

・CSV/TSVファイルの違いは区切り文字の違いだけです。そのためread_csv/read_tableメソッドの違いは区切り文字の違いだけで、両方とも同様に使用することができます。
・read_csv/read_tableメソッドは多くの引数により、細かく動きを決めることができます。
・これによって、別のプログラムが作成・読み取ったデータや、ウェブ上で公開されているデータなどをプログラム内で利用することができます。


この記事が気に入ったらサポートをしてみませんか?