note.nkmk.me

pandasでcsv/tsvファイル読み込み(read_csv, read_table)

Date: 2015-08-09 / Modified: 2018-06-27 / tags: Python, pandas, CSV
このエントリーをはてなブックマークに追加

csvファイル、tsvファイルをpandas.DataFrameとして読み込むには、pandasの関数read_csv()read_table()を使う。

ここでは、

  • read_csv()read_table()の違い
  • headerがないcsvの読み込み
  • headerがあるcsvの読み込み
  • indexがあるcsvの読み込み
  • 列を指定(選択)して読み込み
  • 行をスキップ(除外)して読み込み
  • dtypeを指定して読み込み
  • 欠損値NaNの扱い
  • エンコーディングの指定
  • zipなどで圧縮されたファイルの読み込み
  • Web上のファイルの読み込み
  • tsvの読み込み

について説明する。

csvファイルの書き出しや追記については以下の記事を参照。

そのほかpandasでのExcelファイル、jsonファイルの読み書き(入出力)については以下の記事を参照。

スポンサーリンク

read_csvとread_tableの違い

pandasの関数pd.read_csv()pd.read_table()はデフォルトの区切り文字が違うだけで中身は同じ。

read_csv()は区切り文字がカンマ,read_table()は区切り文字がタブ\t

ソースを見ると同じ関数を呼び出している。

read_csv = _make_parser_function('read_csv', sep=',')
read_csv = Appender(_read_csv_doc)(read_csv)

read_table = _make_parser_function('read_table', sep='\t')
read_table = Appender(_read_table_doc)(read_table)
source: parsers.py

csvファイル(カンマ区切り)を読みたいときはread_csv()、tsvファイル(タブ区切り)を読みたいときはread_table()でOK。

カンマでもタブでもない場合、引数(sepdelimiter)で区切り文字を設定できる。

以下、read_csv()で説明するが、read_tableでも同じ。

headerがないcsvの読み込み

headerがない以下のようなcsvファイルを読み込む。

11,12,13,14
21,22,23,24
31,32,33,34
source: sample.csv

なにも引数を設定しないと、1行目がheaderとして認識される。

import pandas as pd

df = pd.read_csv('data/src/sample.csv')
print(df)
#    11  12  13  14
# 0  21  22  23  24
# 1  31  32  33  34

print(df.columns)
# Index(['11', '12', '13', '14'], dtype='object')

header=Noneとするとpandasが勝手に列名を割り当ててくれる。

df_none = pd.read_csv('data/src/sample.csv', header=None)
print(df_none)
#     0   1   2   3
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34

names=('A', 'B', 'C', 'D')のように任意の値を列名として設定することもできる。リストまたはタプルで指定する。

df_names = pd.read_csv('data/src/sample.csv', names=('A', 'B', 'C', 'D'))
print(df_names)
#     A   B   C   D
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34

headerがあるcsvの読み込み

headerがある以下のようなcsvファイルを読み込む。

a,b,c,d
11,12,13,14
21,22,23,24
31,32,33,34

header=0のようにheaderの行番号を0始まりで指定する。デフォルトがheader=0なので、最初の行がheaderの場合は省略しても同じ結果。

df_header = pd.read_csv('data/src/sample_header.csv')
print(df_header)
#     a   b   c   d
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34

df_header_0 = pd.read_csv('data/src/sample_header.csv', header=0)
print(df_header_0)
#     a   b   c   d
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34

headerで指定した行からデータが読み込まれ、それより上の行は無視される。

df_header_2 = pd.read_csv('data/src/sample_header.csv', header=2)
print(df_header_2)
#    21  22  23  24
# 0  31  32  33  34

indexがあるcsvの読み込み

headerとindex(見出し列)がある以下のようなcsvファイルを読み込む。

,a,b,c,d
ONE,11,12,13,14
TWO,21,22,23,24
THREE,31,32,33,34

何も指定しないと特にindex列は認識されない。

df_header_index = pd.read_csv('data/src/sample_header_index.csv')
print(df_header_index)
#   Unnamed: 0   a   b   c   d
# 0        ONE  11  12  13  14
# 1        TWO  21  22  23  24
# 2      THREE  31  32  33  34

print(df_header_index.index)
# RangeIndex(start=0, stop=3, step=1)

index_col=0のようにindexとして使いたい列の列番号を0始まりで指定する。

df_header_index_col = pd.read_csv('data/src/sample_header_index.csv', index_col=0)
print(df_header_index_col)
#         a   b   c   d
# ONE    11  12  13  14
# TWO    21  22  23  24
# THREE  31  32  33  34

print(df_header_index_col.index)
# Index(['ONE', 'TWO', 'THREE'], dtype='object')

列を指定(選択)して読み込み

引数usecols

特定の列だけを読み込む場合、引数usecolsを使う。

読み込む列番号をリストで指定する。一列だけの場合もリストを使う。

df_none_usecols = pd.read_csv('data/src/sample.csv', header=None, usecols=[1, 3])
print(df_none_usecols)
#     1   3
# 0  12  14
# 1  22  24
# 2  32  34

df_none_usecols = pd.read_csv('data/src/sample.csv', header=None, usecols=[2])
print(df_none_usecols)
#     2
# 0  13
# 1  23
# 2  33

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

df_header_usecols = pd.read_csv('data/src/sample_header.csv', usecols=['a', 'c'])
print(df_header_usecols)
#     a   c
# 0  11  13
# 1  21  23
# 2  31  33

特定の列を除外して読み込む場合、無名関数(ラムダ式)を使うと便利。特に列数が多いファイルから少数の列を除外して読み込みたいたいときは読み込む列番号を大量に指定するより楽。

df_header_usecols = pd.read_csv('data/src/sample_header.csv',
                                usecols=lambda x: x is not 'b')
print(df_header_usecols)
#     a   c   d
# 0  11  13  14
# 1  21  23  24
# 2  31  33  34

df_header_usecols = pd.read_csv('data/src/sample_header.csv',
                                usecols=lambda x: x not in ['a', 'c'])
print(df_header_usecols)
#     b   d
# 0  12  14
# 1  22  24
# 2  32  34

index_colと合わせて使う場合はindex_colで指定する列もusecolsで指定しておく必要がある。

df_index_usecols = pd.read_csv('data/src/sample_header_index.csv',
                               index_col=0, usecols=[0, 1, 3])
print(df_index_usecols)
#         a   c
# ONE    11  13
# TWO    21  23
# THREE  31  33

行をスキップ(除外)して読み込み

引数skiprows

特定の行をスキップ(除外)して読み込む場合、引数skiprowsを使う。

skiprowsに整数を渡すと、ファイルの先頭をその行数分スキップして読み込む。

df_none = pd.read_csv('data/src/sample.csv', header=None)
print(df_none)
#     0   1   2   3
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34

df_none = pd.read_csv('data/src/sample.csv', header=None, skiprows=2)
print(df_none)
#     0   1   2   3
# 0  31  32  33  34

スキップする行番号をリストで指定することもできる。usecolsとは違って、指定するのは読み込む行ではなくスキップする行。

一行だけの場合もリストを使う。

df_none_skiprows = pd.read_csv('data/src/sample.csv', header=None, skiprows=[0, 2])
print(df_none_skiprows)
#     0   1   2   3
# 0  21  22  23  24

df_none_skiprows = pd.read_csv('data/src/sample.csv', header=None, skiprows=[1])
print(df_none_skiprows)
#     0   1   2   3
# 0  11  12  13  14
# 1  31  32  33  34

特定の行だけを読み込む場合は、無名関数(ラムダ式)を使うと便利。特に行数が多いファイルから特定の行だけを読み込みたいたいときはスキップする行番号を指定するより楽。

df_none_skiprows = pd.read_csv('data/src/sample.csv', header=None,
                               skiprows=lambda x: x not in [0, 2])
print(df_none_skiprows)
#     0   1   2   3
# 0  11  12  13  14
# 1  31  32  33  34

headerがあるファイルの場合、headerの行も考慮する必要があるので注意。

df_header_skiprows = pd.read_csv('data/src/sample_header.csv', skiprows=[1])
print(df_header_skiprows)
#     a   b   c   d
# 0  21  22  23  24
# 1  31  32  33  34

df_header_skiprows = pd.read_csv('data/src/sample_header.csv', skiprows=[0, 3])
print(df_header_skiprows)
#    11  12  13  14
# 0  21  22  23  24

なお、indexを指定していてもskiprowsを行名で指定することはできない。

引数skipfooter

ファイルの末尾をスキップする場合、引数skipfooterを使う。スキップする行数を整数で指定する。

環境によっては以下のようなWarningが出るので、引数engine='python'を指定する。

ParserWarning: Falling back to the 'python' engine because the 'c' engine does not support skipfooter; you can avoid this warning by specifying engine='python'.
df_none_skipfooter = pd.read_csv('data/src/sample.csv', header=None,
                                 skipfooter=1, engine='python')
print(df_none_skipfooter)
#     0   1   2   3
# 0  11  12  13  14
# 1  21  22  23  24

引数nrows

最初の数行だけを読み込むこともできる。引数nrowsを使う。

大きいサイズのファイルのデータを少し確認する場合に便利。

df_none_nrows = pd.read_csv('data/src/sample.csv', header=None, nrows=2)
print(df_none_nrows)
#     0   1   2   3
# 0  11  12  13  14
# 1  21  22  23  24

型(dtype)を指定して読み込み

pandas.DataFrameは列ごとに型dtypeが設定されており、astype()メソッドで変換(キャスト)できる。文字列とobject型との関係など詳細は以下の記事を参照。

read_csv()では値から各列の型dtypeが自動的に選択されるが、場合によっては引数dtypeで明示的に指定する必要がある。

以下のファイルを例とする。

,a,b,c,d
ONE,1,"001",100,x
TWO,2,"020",,y
THREE,3,"300",300,z

0で始まる数値の列は引用符で囲まれていてもいなくてもデフォルトでは文字列ではなく数値としてみなされて、先頭の0は省略されてしまう。

df_default = pd.read_csv('data/src/sample_header_index_dtype.csv', index_col=0)
print(df_default)
#        a    b      c  d
# ONE    1    1  100.0  x
# TWO    2   20    NaN  y
# THREE  3  300  300.0  z

print(df_default.dtypes)
# a      int64
# b      int64
# c    float64
# d     object
# dtype: object

print(df_default.applymap(type))
#                    a              b                c              d
# ONE    <class 'int'>  <class 'int'>  <class 'float'>  <class 'str'>
# TWO    <class 'int'>  <class 'int'>  <class 'float'>  <class 'str'>
# THREE  <class 'int'>  <class 'int'>  <class 'float'>  <class 'str'>

先頭の0を含んだ文字列として扱いたい場合は、read_csv()の引数dtypeを指定する。

引数dtypeに任意のデータ型を指定すると、index_colで指定した列も含むすべての列がその型に変換されて読み込まれる。例えばdtype=strとすると、すべての列が文字列にキャストされる。ただし、この場合も欠損値はfloat型。

df_str = pd.read_csv('data/src/sample_header_index_dtype.csv',
                     index_col=0, dtype=str)
print(df_str)
#        a    b    c  d
# ONE    1  001  100  x
# TWO    2  020  NaN  y
# THREE  3  300  300  z

print(df_str.dtypes)
# a    object
# b    object
# c    object
# d    object
# dtype: object

print(df_str.applymap(type))
#                    a              b                c              d
# ONE    <class 'str'>  <class 'str'>    <class 'str'>  <class 'str'>
# TWO    <class 'str'>  <class 'str'>  <class 'float'>  <class 'str'>
# THREE  <class 'str'>  <class 'str'>    <class 'str'>  <class 'str'>

dtype=objectとしても同じ結果となる。

df_object = pd.read_csv('data/src/sample_header_index_dtype.csv',
                        index_col=0, dtype=object)
print(df_object)
#        a    b    c  d
# ONE    1  001  100  x
# TWO    2  020  NaN  y
# THREE  3  300  300  z

print(df_object.dtypes)
# a    object
# b    object
# c    object
# d    object
# dtype: object

print(df_object.applymap(type))
#                    a              b                c              d
# ONE    <class 'str'>  <class 'str'>    <class 'str'>  <class 'str'>
# TWO    <class 'str'>  <class 'str'>  <class 'float'>  <class 'str'>
# THREE  <class 'str'>  <class 'str'>    <class 'str'>  <class 'str'>

型変換(キャスト)できない型を引数dtypeに指定するとエラーになるので注意。この例ではindex_colで指定した文字列のインデックス列を整数int型に変換するところでエラーになっている。

# df_int = pd.read_csv('data/src/sample_header_index_dtype.csv',
#                      index_col=0, dtype=int)
# ValueError: invalid literal for int() with base 10: 'ONE'

読み込んだあとでpandas.DataFrameの列の型を変換するにはastype()メソッドに辞書形式で指定する。詳細は上述の関連記事を参照。

df_str_cast = df_str.astype({'a': int})
print(df_str_cast)
#        a    b    c  d
# ONE    1  001  100  x
# TWO    2  020  NaN  y
# THREE  3  300  300  z

print(df_str_cast.dtypes)
# a     int64
# b    object
# c    object
# d    object
# dtype: object

read_csv()での読み込み時に引数dtypeに辞書形式で列の型を指定することもできる。指定した列以外は自動で選ばれた型となる。

df_str_col = pd.read_csv('data/src/sample_header_index_dtype.csv',
                         index_col=0, dtype={'b': str, 'c': str})
print(df_str_col)
#        a    b    c  d
# ONE    1  001  100  x
# TWO    2  020  NaN  y
# THREE  3  300  300  z

print(df_str_col.dtypes)
# a     int64
# b    object
# c    object
# d    object
# dtype: object

列名だけでなく列番号でも指定できる。インデックス列を指定している場合、インデックス列も含めた列番号で指定する必要があるので注意。

df_str_col_num = pd.read_csv('data/src/sample_header_index_dtype.csv',
                             index_col=0, dtype={2: str, 3: str})
print(df_str_col_num)
#        a    b    c  d
# ONE    1  001  100  x
# TWO    2  020  NaN  y
# THREE  3  300  300  z

print(df_str_col_num.dtypes)
# a     int64
# b    object
# c    object
# d    object
# dtype: object

欠損値NaNの扱い

デフォルトで欠損値とみなされる値

read_csv()およびread_table()ではデフォルトでいくつかの値が欠損値NaNとしてみなされるようになっている。

以下のように空文字列''や文字列'NaN''nan', nullなど、考えられる値は概ねデフォルトで欠損値NaNとして扱われる。

By default the following values are interpreted as NaN: ‘’, ‘#N/A’, ‘#N/A N/A’, ‘#NA’, ‘-1.#IND’, ‘-1.#QNAN’, ‘-NaN’, ‘-nan’, ‘1.#IND’, ‘1.#QNAN’, ‘N/A’, ‘NA’, ‘NULL’, ‘NaN’, ‘n/a’, ‘nan’, ‘null’.
pandas.read_csv — pandas 0.23.0 documentation

以下のファイルを例として動作を確認する。

,a,b
ONE,,NaN
TWO,-,nan
THREE,null,N/A

特に引数を設定せずデフォルトで読み込んでisnull()メソッドで確認すると、対象外の'-'以外は欠損値NaNとして扱われていることが分かる。

df_nan = pd.read_csv('data/src/sample_header_index_nan.csv', index_col=0)
print(df_nan)
#          a   b
# ONE    NaN NaN
# TWO      - NaN
# THREE  NaN NaN

print(df_nan.isnull())
#            a     b
# ONE     True  True
# TWO    False  True
# THREE   True  True

欠損値として扱う値を追加: 引数na_values

デフォルトの値に追加して欠損値として扱う値を指定したい場合は引数na_valuesを使う。

df_nan_set_na = pd.read_csv('data/src/sample_header_index_nan.csv',
                            index_col=0, na_values='-')
print(df_nan_set_na)
#         a   b
# ONE   NaN NaN
# TWO   NaN NaN
# THREE NaN NaN

print(df_nan_set_na.isnull())
#           a     b
# ONE    True  True
# TWO    True  True
# THREE  True  True

リストで指定すると複数の値を追加できる。

欠損値として扱う値を指定: 引数na_values, keep_default_na

引数keep_default_naFalseとしたうえで引数na_valuesに値を指定すると、na_valuesに指定した値のみが欠損値として扱われる。na_valuesに指定しない限り、デフォルトの値は欠損値として扱われない。

df_nan_set_na_no_keep = pd.read_csv('data/src/sample_header_index_nan.csv',
                                    index_col=0, na_values=['-', 'NaN', 'null'],
                                    keep_default_na=False)
print(df_nan_set_na_no_keep)
#          a    b
# ONE         NaN
# TWO    NaN  nan
# THREE  NaN  N/A

print(df_nan_set_na_no_keep.isnull())
#            a      b
# ONE    False   True
# TWO     True  False
# THREE   True  False

どの値も欠損値として扱わない: 引数na_filter

引数na_filterFalseとすると、引数na_values, keep_default_naの指定によらずすべての値がそのままの文字列として読み込まれ、欠損値として扱われない。

df_nan_no_filter = pd.read_csv('data/src/sample_header_index_nan.csv',
                               index_col=0, na_filter=False)
print(df_nan_no_filter)
#           a    b
# ONE          NaN
# TWO       -  nan
# THREE  null  N/A

print(df_nan_no_filter.isnull())
#            a      b
# ONE    False  False
# TWO    False  False
# THREE  False  False

エンコーディングの指定

エンコーディングは引数encodingで指定する。

デフォルト(省略した場合)はutf-8で、utf-8ではないファイルに対しては文字化けするのではなくエラーUnicodeDecodeErrorになる。

# df_sjis = pd.read_csv('data/src/sample_header_shift_jis.csv')
# UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 0: invalid start byte

正しいエンコーディングを指定するとOK。

df_sjis = pd.read_csv('data/src/sample_header_shift_jis.csv',
                      encoding='shift_jis')
print(df_sjis)
#    a   b   c   d
# 0  あ  12  13  14
# 1  い  22  23  24
# 2  う  32  33  34

shift_jiscp932のファイルを扱う場合は注意。

zipなどで圧縮されたファイルの読み込み

zipなどで圧縮されたcsvファイルをそのまま読み込むこともできる。

df_zip = pd.read_csv('data/src/sample_header.csv.zip')
print(df_zip)
#     a   b   c   d
# 0  11  12  13  14
# 1  21  22  23  24
# 2  31  32  33  34

拡張子が.gz, .bz2, .zip, .xzの場合、自動で検出して展開してくれる。拡張子が異なる場合、引数compressionに文字列'gz', 'bz2', 'zip', 'xz'を明示的に指定する。

なお、対応しているのはcsvファイル単体が圧縮されている場合のみ。複数ファイルが圧縮されている場合はエラーになる。

zipxzはバージョン0.18.1からの対応。

Web上のファイルの読み込み

これまでの例はローカルのファイルを指定してきたが、第一引数にはURLを指定することも可能。Web上のファイルを直接読み込める。

ただし、多くの場合、引数を適宜指定しないと読み込めなかったり余計なデータが含まれてしまったりするので何度か試行する必要がある。特にサイズの大きいファイルの場合はローカルにダウンロードしてトライしたほうがいいかもしれない。

東京都の郵便番号データを例とする。

df = pd.read_csv('http://www.post.japanpost.jp/zipcode/dl/oogaki/zip/13tokyo.zip',
                 header=None, encoding='shift_jis')

print(df.shape)
# (3851, 15)

print(df.head())
#       0    1        2       3      4                5    6     7           8   \
# 0  13101  100  1000000  トウキヨウト  チヨダク  イカニケイサイガナイバアイ  東京都  千代田区  以下に掲載がない場合   
# 1  13101  102  1020072  トウキヨウト  チヨダク          イイダバシ  東京都  千代田区         飯田橋   
# 2  13101  102  1020082  トウキヨウト  チヨダク         イチバンチヨウ  東京都  千代田区         一番町   
# 3  13101  101  1010032  トウキヨウト  チヨダク          イワモトチヨウ  東京都  千代田区         岩本町   
# 4  13101  101  1010047  トウキヨウト  チヨダク           ウチカンダ  東京都  千代田区         内神田   
#    9   10  11  12  13  14  
# 0   0   0   0   0   0   0  
# 1   0   0   1   0   0   0  
# 2   0   0   0   0   0   0  
# 3   0   0   1   0   0   0  
# 4   0   0   1   0   0   0  

print(df.tail())
#          0      1        2       3                  4                5    6   \
# 3846  13401  10015  1001511  トウキヨウト  ハチジヨウジマハチジヨウマチ              ミツネ  東京都   
# 3847  13402  10017  1001701  トウキヨウト           アオガシマムラ     アオガシマムライチエン  東京都   
# 3848  13421  10021  1002100  トウキヨウト           オガサワラムラ  イカニケイサイガナイバアイ  東京都   
# 3849  13421  10021  1002101  トウキヨウト           オガサワラムラ            チチジマ  東京都   
# 3850  13421  10022  1002211  トウキヨウト           オガサワラムラ            ハハジマ  東京都   
#           7           8   9   10  11  12  13  14  
# 3846  八丈島八丈町          三根   0   0   0   0   0   0  
# 3847    青ヶ島村      青ヶ島村一円   0   0   0   0   0   0  
# 3848    小笠原村  以下に掲載がない場合   0   0   0   0   0   0  
# 3849    小笠原村          父島   0   0   0   0   0   0  
# 3850    小笠原村          母島   0   0   0   0   0   0  

tsvの読み込み

はじめに書いた通り、tsvファイル(タブ区切り)を読みたいときはread_table()を使えばよい。

以下のようなファイルの場合。

    a   b   c   d
ONE 11  12  13  14
TWO 21  22  23  24
THREE   31  32  33  34

引数などはread_csv()と同じ。

df_tsv = pd.read_table('data/src/sample_header_index.tsv', index_col=0)
print(df_tsv)
#         a   b   c   d
# ONE    11  12  13  14
# TWO    21  22  23  24
# THREE  31  32  33  34

read_csv()で区切り文字にタブ文字\tを設定しても読める。

df_tsv_sep = pd.read_csv('data/src/sample_header_index.tsv', index_col=0, sep='\t')
print(df_tsv_sep)
#         a   b   c   d
# ONE    11  12  13  14
# TWO    21  22  23  24
# THREE  31  32  33  34
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事