PythonでPandasを使ってCSVファイルの読み書きをする

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 47 が欠落していることに注意してください。

ヘッダーの取り外し

ヘッダーを完全に削除することもできます。

この場合、 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に欠損値があり、NaNNAとして残しておくことがあります。

このような場合、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 メソッドを呼び出す必要があります。

タイトルとURLをコピーしました