Pythonでは、組み込みの open()
関数や専用のcsvモジュールを使ってCSVファイルの読み書きができますが、Pandasを使うこともできます。
この記事では、PythonのPandasライブラリを使ってCSVファイルの読み書きをする方法を紹介します。
CSVファイルとは?
CSVファイルとは、いくつかの書式規則に従った単純なテキストファイルに過ぎないことを簡単に復習しておきましょう。
しかし、表形式のデータを保存する方法としては、最も一般的でシンプル、かつ簡単な方法です。
この形式は、行と列に分けられた特定の構造に従ってテーブルを配置します。
データを格納するのは、これらの行と列です。
各行が改行され、次の行が始まります。
同様に、区切り記号(通常はカンマ)で各行内の列を区切ります。
例えば、次のような表があるとします。
| City | State | Capital | Population |
| ------------ | ------------ | ------- | ------------- |
| Philadelphia | Pennsylvania | No | 1.581 Million |
| Sacramento | California | Yes | 0.5 Million |
| New York | New York | No | 8.623 Million |
| Austin | Texas | Yes | 0.95 Million |
| Miami | Florida | No | 0.463 Million |
これをCSV形式に変換すると、次のようになります。
City,State,Capital,Population
Philadelphia,Pennsylvania,No,1.581 Million
Sacramento,California,Yes,0.5 Million
New York,New York,No,8.623 Million
Austin,Texas,Yes,0.95 Million
Miami,Florida,No,0.463 Million
名前(Comma-Separated Values)は本来カンマを区切り文字として使用しますが、セミコロン(;
)など他の区切り文字(セパレータ)も使用することができます。
表の各行はCSVファイルの新しい行であり、表形式のデータを表すには非常にコンパクトで簡潔な方法です。
では、read_csv()
関数を見てみましょう。
Pandasを使ったCSVファイルの読み出しと書き込み
Pandasはデータ分析・操作のための非常に強力で人気のあるフレームワークです。
Pandasの最も顕著な特徴の1つは、CSVやExcelを含む様々な種類のファイルを読み書きできることです。
Pandas では read_csv()
や to_csv()
などの関数を使って、CSV ファイルを効果的かつ簡単に操作することができます。
Pandasのインストール
Pandasを使用する前に、Pandasをインストールする必要があります。
ここでは、pip
を使用します。
$ pip install pandas
read_csv()によるCSVファイルの読み込み
GitHubで公開されているTitanic Datasetをインポートしてみましょう。
import pandas as pd
titanic_data = pd.read_csv('titanic.csv')
Pandasはこのファイルをスクリプトのディレクトリから探します。
このメソッドの唯一の必須引数として、パースしたいファイルへのファイルパスを指定します。
このデータセットの head()
を見て、正しくインポートされていることを確認しましょう。
titanic_data.head()
この結果は
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 4 1 1 ... 53.1000 C123 S
4 5 0 3 ... 8.0500 NaN S
また、GitHub などのオンラインリソースから CSV ファイルを読み込むこともできます。
この場合は、リソースの URL を read_csv()
関数に渡します。
同じ CSV ファイルを GitHub リポジトリから読み込んでみましょう。
import pandas as pd
titanic_data = pd.read_csv(r'https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv')
print(titanic_data.head())
この結果も
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 4 1 1 ... 53.1000 C123 S
4 5 0 3 ... 8.0500 NaN S
[5 rows x 12 columns]
ヘッダーのカスタマイズ
デフォルトでは、read_csv()
メソッドは CSV ファイルの最初の行をカラムヘッダとして使用します。
時には、これらのヘッダが奇妙な名前であったり、独自のヘッダを使用したい場合もあるでしょう。
ヘッダを設定するには、ファイルを読み込んだ後に、 DataFrame
インスタンスの columns
フィールドに別のリストを代入するか、そもそも CSV を読み込む際にヘッダを設定します。
ここでは、カラム名のリストを定義して、CSV ファイルのカラム名の代わりに、それらのカラム名を使用することにしましょう。
import pandas as pd
col_names = ['Id',
'Survived',
'Passenger Class',
'Full Name',
'Gender',
'Age',
'SibSp',
'Parch',
'Ticket Number',
'Price', 'Cabin',
'Station']
titanic_data = pd.read_csv(r'E:Datasets itanic.csv', names=col_names)
print(titanic_data.head())
このコードを実行してみましょう。
Id Survived Passenger Class ... Price Cabin Station
0 PassengerId Survived Pclass ... Fare Cabin Embarked
1 1 0 3 ... 7.25 NaN S
2 2 1 1 ... 71.2833 C85 C
3 3 1 3 ... 7.925 NaN S
4 4 1 1 ... 53.1 C123 S
ふむ、これでカスタムヘッダーができました。
しかし、元々カラム名を設定するために使用されていたCSVファイルの最初の行も DataFrame
に含まれています。
この行はもはや何の価値もないので、読み飛ばしたいところです。
CSV読み込み時の行スキップについて
この問題を解決するために、引数 skiprows
を使ってみましょう。
import pandas as pd
col_names = ['Id',
'Survived',
'Passenger Class',
'Full Name',
'Gender',
'Age',
'SibSp',
'Parch',
'Ticket Number',
'Price', 'Cabin',
'Station']
titanic_data = pd.read_csv(r'E:Datasets itanic.csv', names=col_names, skiprows=[0])
print(titanic_data.head())
では、このコードを実行してみましょう。
Id Survived Passenger Class ... Price Cabin Station
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 4 1 1 ... 53.1000 C123 S
4 5 0 3 ... 8.0500 NaN S
見事に成功です。
引数 skiprows
には、スキップしたい行を列挙することができます。
例えば、0, 4, 7
のような行をスキップすることもできます。
titanic_data = pd.read_csv(r'E:Datasets itanic.csv', names=col_names, skiprows=[0, 4, 7])
print(titanic_data.head(10))
この結果、今まで見てきたような行がない DataFrame
ができあがります。
Id Survived Passenger Class ... Price Cabin Station
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 5 0 3 ... 8.0500 NaN S
4 6 0 3 ... 8.4583 NaN Q
5 8 0 3 ... 21.0750 NaN S
6 9 1 3 ... 11.1333 NaN S
7 10 1 2 ... 30.0708 NaN C
8 11 1 3 ... 16.7000 G6 S
9 12 1 1 ... 26.5500 C103 S
行のスキップは DataFrame
が完全に形成される前に行われるので、DataFrame
自体のインデックスが欠落することはありませんが、この場合、(CSV ファイルから取り込んだ) Id
フィールドの ID 4
と 7
が欠落していることに注意してください。
ヘッダーの取り外し
ヘッダーを完全に削除することもできます。
この場合、 header
引数を None
に設定することで、 0...n
のヘッダー列を持つ DataFrame
を作成することができます。
titanic_data = pd.read_csv(r'E:Datasets itanic.csv', header=None, skiprows=[0])
また、ここでは最初の行をスキップするようにします。
そうしないと、最初の行の値も実際に含まれてしまうからです。
0 1 2 3 4 ... 7 8 9
0 1 0 3 Braund, Mr. Owen Harris male ... 0 A/5 21171 7.2500
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female ... 0 PC 17599 71.2833
2 3 1 3 Heikkinen, Miss. Laina female ... 0 STON/O2. 3101282 7.9250
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female ... 0 113803 53.1000
4 5 0 3 Allen, Mr. William Henry male ... 0 373450 8.0500
デリミタの指定
先に述べたように、実際にはカンマでデータを区切らないCSVファイルに遭遇することがあるでしょう。
そのような場合は、sep
引数で他のデリミタを指定します。
titanic_data = pd.read_csv(r'E:Datasets itanic.csv', sep=';')
to_csv()によるCSVファイルの書き方
繰り返しになりますが、DataFrame
は表形式です。
DataFrameを CSV ファイルに変換するのは、CSV ファイルを
DataFrameに変換するのと同じくらい簡単で、
DataFrameのインスタンスに対して
write_csv()` 関数を呼び出して行います。
DataFrameを CSV ファイルに書き出す際には、
columns引数でカラム名を変更したり、
sep` 引数でデリミタを指定したりすることができる。
もし、どちらも指定しなかった場合は、標準的なカンマ区切り値のファイルになってしまいます。
これで遊んでみましょう。
import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida']], columns=['City', 'State'])
cities.to_csv('cities.csv')
ここでは、2つの都市とそれぞれの州を含む単純な DataFrame
を作成しました。
そして、そのデータを to_csv()
とファイル名を指定して CSV ファイルに保存しています。
この結果、実行しているスクリプトの作業ディレクトリに新しいファイルが作成され、その中には以下の内容が含まれています。
,City,State
0,Sacramento,California
1,Miami,Florida
しかし、これはあまり整った形式ではありません。
データフレームのインデックスが残っていますし、カラム名の前に変な欠落があります。
このCSVをDataFrame`に再インポートしたら、とんでもないことになりそうです。
df = pd.read_csv('cities.csv')
print(df)
この結果、次のようになります。
Unnamed: 0 City State
0 0 Sacramento California
1 1 Miami Florida
DataFrameのインデックスが新しいカラムになり、
Unnamed` になってしまいました。
ファイルを保存するときには、DataFrame
のインデックスを削除するようにしましょう。
import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida']], columns=['City', 'State'])
cities.to_csv('cities.csv', index=False)
さて、この結果、ファイルに含まれるのは
City,State
Sacramento,California
Miami,Florida
これで問題なく動作するようになりました。
再インポートして内容を表示すると、DataFrame
がうまく構築されています。
df = pd.read_csv('cities.csv')
print(df)
この結果、次のようになります。
City State
0 Sacramento California
1 Miami Florida
ヘッダーのカスタマイズ
カラムのヘッダーをデフォルトのものから変更してみましょう。
import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida']], columns=['City', 'State'])
new_column_names = ['City_Name', 'State_Name']
cities.to_csv('cities.csv', index=False, header=new_column_names)
新しいヘッダリストを作成し、カラムに対応するさまざまな値を格納します。
そして、header引数を使用して、元のカラム名の代わりにこれらの値を設定します。
この結果、以下のような内容のcities.csv` が生成されます。
City_Name,State_Name
Sacramento,California
Miami,Florida
Washington DC,Unknown
デリミターのカスタマイズ
デリミターをデフォルトの(,
)から新しいものに変更してみましょう。
import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida']], columns=['City', 'State'])
cities.to_csv('cities.csv', index=False, sep=';')
この結果、cities.csv
ファイルに以下の内容が含まれるようになります。
City;State
Sacramento;California
Miami;Florida
欠測値の取り扱い
時々、DataFrame
に欠損値があり、NaN
やNA
として残しておくことがあります。
このような場合、CSVファイルに書き出す際に、これらをフォーマットしたいと思うかもしれません。
引数 na_rep
を使って、欠損値の代わりに入れるべき値を設定することができる。
import pandas as pd
cities = pd.DataFrame([['Sacramento', 'California'], ['Miami', 'Florida'], ['Washington DC', pd.NA]], columns=['City', 'State'])
cities.to_csv('cities.csv', index=False, na_rep='Unknown')
ここでは、2つの有効な都市と州のペアがありますが、Washington DC
は州が抜けています。
このコードを実行すると、次のような内容の cities.csv
が生成されます。
City,State
Sacramento,California
Miami,Florida
Washington DC,Unknown
結論
PythonのPandasライブラリを使ってCSVファイルの読み書きをする方法を紹介しました。
CSVファイルを読み込むには、Pandasライブラリの read_csv()
メソッドを使用します。
また、read_csv()
メソッドの names
属性により、CSVファイルの読み込み時にカスタムヘッダー名を渡すことができます。
最後に、Pandasを使用してCSVファイルを書き込むには、まずPandas DataFrameオブジェクトを作成し、そのDataFrameに対して to_csv
メソッドを呼び出す必要があります。