[解決!Python]CSVファイルから読み込みを行うには(pandas編)解決!Python

pandasが提供するread_csv関数を使って、CSVファイルなどからデータを読み込む方法を紹介する。

» 2023年12月01日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

* 本稿は2021年9月7日に公開された記事をPython 3.12.0で動作確認したものです(確認日:2023年12月1日)。


import pandas as pd
from pathlib import Path

filepath = 'test0.csv'
print(Path(filepath).read_text())
#0.0,1.1,2.2
#3.3,4.4,5.5
#6.6,7.7,8.8

df = pd.read_csv(filepath)
print(df)
#   0.0  1.1  2.2
#0  3.3  4.4  5.5
#1  6.6  7.7  8.8

# ヘッダー行がないことを指定
df = pd.read_csv(filepath, header=None)
print(df)
#     0    1    2
#0  0.0  1.1  2.2
#1  3.3  4.4  5.5
#2  6.6  7.7  8.8

# 列名を指定
names = ['col0', 'col1', 'col2']
df = pd.read_csv(filepath, names=names)
print(df)
#   col0  col1  col2
#0   0.0   1.1   2.2
#1   3.3   4.4   5.5
#2   6.6   7.7   8.8

# ヘッダー行がある場合
filepath = 'test1.csv'
print(Path(filepath).read_text())
#col0,col1,col2
#0.0,1.1,2.2
#3.3,4.4,5.5
#6.6,7.7,8.8

df = pd.read_csv(filepath)
print(df)
#   col0  col1  col2  # ヘッダー行から列名を推測してくれる
#0   0.0   1.1   2.2
#1   3.3   4.4   5.5
#2   6.6   7.7   8.8

# 列名をヘッダー行から推測せずに、明示的に指定する
names = ['foo', 'bar', 'baz']
df = pd.read_csv(filepath, names=names, header=0)
print(df)
#   foo  bar  baz
#0  0.0  1.1  2.2
#1  3.3  4.4  5.5
#2  6.6  7.7  8.8

# 区切り文字の指定
filepath = 'test2.csv'
print(Path(filepath).read_text())
#col0 col1 col2  # 空白文字で区切っている
#0.0 1.1 2.2
#3.3 4.4 5.5
#6.6 7.7 8.8

df = pd.read_csv(filepath, sep=' ')
print(df)
#  col0 col1 col2
#0    0.0 1.1 2.2
#1    3.3 4.4 5.5
#2    6.6 7.7 8.8

# 読み込む列の指定
filepath = 'test1.csv'
df = pd.read_csv(filepath, usecols=[0, 2])
print(df)
#   col0  col2
#0   0.0   2.2
#1   3.3   5.5
#2   6.6   8.8

df = pd.read_csv(filepath, usecols=['col0', 'col2'])
print(df)  # 出力は省略

df = pd.read_csv(filepath, usecols=lambda x: x in ['col0', 'col2'])
print(df)  # 出力は省略

# 行ラベル(インデックス)となる列の指定
filepath = 'test3.csv'
print(Path(filepath).read_text())
#IDX,col1,col2,col3
#row0,0.0,1.1,2.2
#row1,3.3,4.4,5.5
#row2,6.6,7.7,8.8

df = pd.read_csv(filepath, index_col=0)
print(df)
#      col1  col2  col3
#IDX                  
#row0   0.0   1.1   2.2
#row1   3.3   4.4   5.5
#row2   6.6   7.7   8.8

df = pd.read_csv(filepath, index_col='IDX')
print(df)  # 出力は省略

# データ型の指定
filepath = 'test4.csv'
print(Path(filepath).read_text())
#area,tel,value
#tokyo,0312345678,1.0
#kanagawa,045678901,2.0
#chiba,043210987,3.0

df = pd.read_csv(filepath)
print(df)
#       area        tel  value  # 電話番号が整数値になっている
#0     tokyo  312345678    1.0
#1  kanagawa   45678901    2.0
#2     chiba   43210987    3.0

df = pd.read_csv(filepath, dtype=str)  # 全てのデータの型をstrに
print(df)
#       area         tel value
#0     tokyo  0312345678   1.0
#1  kanagawa   045678901   2.0
#2     chiba   043210987   3.0

df = pd.read_csv(filepath, dtype={0: str, 1: str, 2: float})
print(df)  # 出力は省略

# 日付のパース
filepath = 'test5.csv'
print(Path(filepath).read_text())
#date,value0,value1
#2021/09/07,1.0,2.0
#2021/09/08,3.0,4.0
#2021/09/09,5.0,5.0

df = pd.read_csv(filepath, parse_dates=True, index_col=0)
print(df)
#            value0  value1
#date                     
#2021-09-07     1.0     2.0
#2021-09-08     3.0     4.0
#2021-09-09     5.0     5.0

df = pd.read_csv(filepath, parse_dates=[0])
print(df)
#        date  value0  value1
#0 2021-09-07     1.0     2.0
#1 2021-09-08     3.0     4.0
#2 2021-09-09     5.0     5.0

df = pd.read_csv(filepath, parse_dates=['date'])
print(df)  # 出力は省略

filepath = 'test6.csv'
print(Path(filepath).read_text())
#year,month,day,value0,value1
#2021,9,7,1.0,2.0
#2021,9,8,3.0,5.0
#2021,9,9,4.0,6.0

dates = [['year', 'month', 'day']]
df = pd.read_csv(filepath, parse_dates=dates)
print(df)
#  year_month_day  value0  value1
#0     2021-09-07     1.0     2.0
#1     2021-09-08     3.0     5.0
#2     2021-09-09     4.0     6.0

dates = {'date': ['year', 'month', 'day']}
df = pd.read_csv(filepath, parse_dates=dates)
print(df)
#        date  value0  value1
#0 2021-09-07     1.0     2.0
#1 2021-09-08     3.0     5.0
#2 2021-09-09     4.0     6.0

# 欠損値の扱い
filepath = 'test7.csv'
print(Path(filepath).read_text())
# col0,col1,col2
# ,nan,1.0
# 2.0,N/A,null
# NaN,3.0,--

df = pd.read_csv(filepath)
print(df)
#   col0  col1 col2
#0   NaN   NaN  1.0
#1   2.0   NaN  NaN
#2   NaN   3.0   --  # 「--」という文字列は欠損値としては扱われていない

df = pd.read_csv(filepath, na_values=['--'])
print(df)
#   col0  col1  col2  # デフォルトの欠損値とna_valuesに指定した値が欠損値
#0   NaN   NaN   1.0
#1   2.0   NaN   NaN
#2   NaN   3.0   NaN

df = pd.read_csv(filepath, keep_default_na=False,  na_values=['--'])
print(df)
#  col0 col1  col2  # na_valuesに指定した値のみが欠損値として扱われる
#0       nan   1.0
#1  2.0  N/A  null
#2  NaN  3.0   NaN


基本的な使い方

 pandasのread_csv関数を使うと、CSVファイルの内容をpandas.DataFrameオブジェクトに読み込める。読み込んだ内容はpandasが提供するさまざまな機能を使って、参照したり加工したりできる。

 read_csv関数の構文を以下に示す。なお、記述しているパラメーターは本稿で取り上げるものだけだ。詳細についてはpandasのドキュメント「read_csv関数」を参照されたい

pandas.read_csv(filepath, sep, header, names, index_col, usecols, dtype,
                keep_default_na, na_values, parse_date)


 これらのパラメーターについて簡単にまとめる。

  • filepath:読み込むCSVファイルの名前。必須
  • sep:区切り文字の指定(delimiterパラメーターも使える。ただし、両者を同時に指定することはできない)。省略可。省略時はカンマ「,」が指定されたものとして扱われる
  • header:ヘッダー行の指定。省略可。省略時は読み込んだ内容からヘッダー行と列名を推測する
  • names:列名の指定。省略可
  • index_col:行ラベル(行にアクセスするためのインデックス)となる列の指定。省略可。省略時は各行には整数値でアクセスする
  • usecols:読み込む列の指定。省略可。省略時は全ての列の内容が読み込まれる
  • dtype:データ全体または特定列のデータのデータ型を指定。省略可。省略時はデータの内容に応じて自動的にデータ型が推測される
  • keep_default_na:na_valuesパラメーターに欠損値と見なされる値が指定された場合に、デフォルトで欠損値として見なしている値を保持するかどうかの指定。省略可。省略時はTrueが指定されたものとして見なされる(デフォルトの欠損値を保持する)
  • na_values:欠損値として見なされる値の追加指定。省略可
  • parse_dates:日付としてパースするかどうかの指定

 最も基本的な使い方を以下に示す。なお、以下では読み込むCSVファイルの内容を示した後に、read_csv関数を呼び出して、読み込んだ値を表示することにする。

import pandas as pd
from pathlib import Path

filepath = 'test0.csv'
print(Path(filepath).read_text())
#0.0,1.1,2.2
#3.3,4.4,5.5
#6.6,7.7,8.8

df = pd.read_csv(filepath)
print(df)
#   0.0  1.1  2.2
#0  3.3  4.4  5.5
#1  6.6  7.7  8.8


 この例では、read_csv関数を使って3行3列のCSVファイルから読み込みを行っている。ただし、先頭行(0.0,1.1,2.2)がヘッダー行と見なされてしまっている(その内容から列名が「0.0」「1.1」「2.2」と自動的に推測されてもいる)。ヘッダー行がないことを知らせるには、次のようにする。

df = pd.read_csv(filepath, header=None)
print(df)
#     0    1    2
#0  0.0  1.1  2.2
#1  3.3  4.4  5.5
#2  6.6  7.7  8.8


 header=Noneを指定したことで、CSVファイルの先頭行がヘッダー行として扱われなくなり、ヘッダー行から推測されていた列名の代わりに「0」「1」「2」という列名が付けられている。

 列名を明示的に指定するには、namesパラメーターにそれらを指定する。以下に例を示す。

names = ['col0', 'col1', 'col2']
df = pd.read_csv(filepath, names=names)
print(df)
#   col0  col1  col2
#0   0.0   1.1   2.2
#1   3.3   4.4   5.5
#2   6.6   7.7   8.8


 一方、CSVファイルにヘッダー行があるときには、既に見たように自動的にヘッダー行が認識され、列名が推測される。

filepath = 'test1.csv'
print(Path(filepath).read_text())
#col0,col1,col2
#0.0,1.1,2.2
#3.3,4.4,5.5
#6.6,7.7,8.8

df = pd.read_csv(filepath)
print(df)
#   col0  col1  col2  # ヘッダー行から列名を推測してくれる
#0   0.0   1.1   2.2
#1   3.3   4.4   5.5
#2   6.6   7.7   8.8


 列名をヘッダー行の内容と異なるものにするのであれば、以下のようにヘッダー行を明示的に指定するとともに、namesパラメーターに列名を与える。

names = ['foo', 'bar', 'baz']
df = pd.read_csv(filepath, names=names, header=0)
print(df)
#   foo  bar  baz
#0  0.0  1.1  2.2
#1  3.3  4.4  5.5
#2  6.6  7.7  8.8


 この例では、「header=0」としてヘッダー行が先頭行であることを指定し、同時にnamesパラメーターに['foo', 'bar', 'baz']というリストを与えているので、列名がヘッダー行とは異なるものになっている。

 ヘッダー行が複数ある場合には、header=[0, 1]などと指定することも可能だ(この場合は、先頭行とその次の行の値を要素とするタプルが列にアクセスするためのインデックスとなる)。

区切り文字の指定

 区切り文字を指定するには、sepパラメーターまたはdelimiterパラメーターにそれを指定する。以下は、空白文字を区切り文字とするファイルから読み込みを行う例だ。

filepath = 'test2.csv'
print(Path(filepath).read_text())
#col0 col1 col2  # 空白文字で区切っている
#0.0 1.1 2.2
#3.3 4.4 5.5
#6.6 7.7 8.8

df = pd.read_csv(filepath, sep=' ')
print(df)
#  col0 col1 col2
#0    0.0 1.1 2.2
#1    3.3 4.4 5.5
#2    6.6 7.7 8.8


 「sep=None」「engine='python'」を指定することで、区切り文字の自動推測が可能になる。

df = pd.read_csv(filepath, sep=None, engine='python')


読み込む列の指定

 元のCSVファイルから特定の列の内容だけを読み込みたいときには、usecolsパラメーターに読み込みたい列を指定する。以下に例を示す。

filepath = 'test1.csv'
df = pd.read_csv(filepath, usecols=[0, 2])
print(df)
#   col0  col2
#0   0.0   2.2
#1   3.3   5.5
#2   6.6   8.8


 この例では、第0列と第2列の内容だけを読み込むように指定している。列名をusecolsパラメーターに指定してもよい。

df = pd.read_csv(filepath, usecols=['col0', 'col2'])
print(df)  # 出力は省略


 usecolsパラメーターにラムダ式を渡すこともできる。ラムダ式を渡した場合、そのラムダ式には列名が渡され、それを使ったラムダ式の評価結果がTrueとなる列のみが読み込まれる。

df = pd.read_csv(filepath, usecols=lambda x: x in ['col0', 'col2'])
print(df)  # 出力は省略


 この例では、列名は'col0'、'col1'、'col2'の3つであり、それらがラムダ式に渡される。ラムダ式では「列名 in ['col0', 'col2']」が評価されるので、第1列('col1')以外の2列が読み込まれる。

行ラベル(インデックス)となる列の指定

 行ラベル(行にアクセスするためのインデックス)として使用する列を指定するには、index_colパラメーターにその値(整数、列名)を指定する。以下に例を示す。

filepath = 'test3.csv'
print(Path(filepath).read_text())
#IDX,col1,col2,col3
#row0,0.0,1.1,2.2
#row1,3.3,4.4,5.5
#row2,6.6,7.7,8.8

df = pd.read_csv(filepath, index_col=0)
print(df)
#      col1  col2  col3
#IDX                  
#row0   0.0   1.1   2.2
#row1   3.3   4.4   5.5
#row2   6.6   7.7   8.8


 あるいは列名を指定してもよい。

df = pd.read_csv(filepath, index_col='IDX')
print(df)  # 出力は省略


データ型の指定

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

AI for エンジニアリング
「サプライチェーン攻撃」対策
1P情シスのための脆弱性管理/対策の現実解
OSSのサプライチェーン管理、取るべきアクションとは
Microsoft & Windows最前線2024
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。