PythonでCSVファイルを読み書きする

PythonでCSVファイルを読み書きする

それに直面してみましょう。キーボードとコンソールだけでなく、プログラムに情報を出し入れする必要があります。 テキストファイルを介した情報交換は、プログラム間で情報を共有する一般的な方法です。 データを交換するための最も一般的な形式の1つはCSV形式です。 しかし、どうやってそれを使うのですか?

1つ明確にしましょう。独自のCSVパーサーをゼロから作成する必要はありません(また、作成しません)。 使用できる完全に受け入れ可能なライブラリがいくつかあります。 Pythoncsv libraryは、ほとんどの場合に機能します。 作業に大量のデータまたは数値分析が必要な場合、pandas libraryにはCSV解析機能もあり、残りを処理する必要があります。

この記事では、Pythonを使用してテキストファイルからCSVを読み取り、処理し、解析する方法を学びます。 CSVファイルがどのように機能するかを確認し、Pythonに組み込まれている非常に重要なcsvライブラリを学習し、pandasライブラリを使用してCSV解析がどのように機能するかを確認します。

それでは始めましょう!

__ Take the Quiz:インタラクティブな「PythonでのCSVファイルの読み取りと書き込み」クイズで知識をテストします。 完了すると、学習の進捗状況を経時的に追跡できるようにスコアを受け取ります。

CSVファイルとは何ですか?

CSVファイル(カンマ区切り値ファイル)は、特定の構造化を使用して表形式のデータを整理するプレーンテキストファイルの一種です。 プレーンテキストファイルであるため、実際のテキストデータ、つまり印刷可能なASCIIまたはUnicode文字のみを含めることができます。

CSVファイルの構造は、名前で指定されます。 通常、CSVファイルはコンマを使用して特定の各データ値を区切ります。 その構造は次のようになります。

column 1 name,column 2 name, column 3 name
first row data 1,first row data 2,first row data 3
second row data 1,second row data 2,second row data 3
...

各データがカンマで区切られていることに注意してください。 通常、最初の行は各データ、つまりデータ列の名前を識別します。 その後のすべての行は実際のデータであり、ファイルサイズの制約によってのみ制限されます。

一般に、区切り文字は区切り文字と呼ばれ、使用されるのはコンマだけではありません。 その他の一般的な区切り文字には、タブ( )、コロン(:)、およびセミコロン(;)文字が含まれます。 CSVファイルを正しく解析するには、使用されている区切り文字を知る必要があります。

CSVファイルはどこから来たのですか?

CSVファイルは通常、大量のデータを処理するプログラムによって作成されます。 これらは、スプレッドシートやデータベースからデータをエクスポートしたり、他のプログラムでインポートしたり使用したりする便利な方法です。 たとえば、データマイニングプログラムの結果をCSVファイルにエクスポートし、それをスプレッドシートにインポートして、データを分析したり、プレゼンテーション用のグラフを生成したり、公開用のレポートを準備したりできます。

CSVファイルはプログラムで簡単に操作できます。 テキストファイルの入力と文字列操作(Pythonなど)をサポートする言語は、CSVファイルを直接操作できます。

Pythonの組み込みCSVライブラリを使用したCSVファイルの解析

csv libraryは、CSVファイルの読み取りと書き込みの両方を行う機能を提供します。 Excelで生成されたCSVファイルをそのまま使用できるように設計されており、さまざまなCSV形式で動作するように簡単に適応できます。 csvライブラリには、CSVファイルとの間でデータの読み取り、書き込み、および処理を行うためのオブジェクトとその他のコードが含まれています。

csvでCSVファイルを読み取る

CSVファイルからの読み取りは、readerオブジェクトを使用して行われます。 CSVファイルは、ファイルオブジェクトを返すPythonの組み込みopen()関数を使用してテキストファイルとして開かれます。 次に、これはreaderに渡され、重労働が行われます。

employee_birthday.txtファイルは次のとおりです。

name,department,birthday month
John Smith,Accounting,November
Erica Meyers,IT,March

これを読むためのコードは次のとおりです。

import csv

with open('employee_birthday.txt') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            print(f'Column names are {", ".join(row)}')
            line_count += 1
        else:
            print(f'\t{row[0]} works in the {row[1]} department, and was born in {row[2]}.')
            line_count += 1
    print(f'Processed {line_count} lines.')

これにより、次のような出力が得られます。

Column names are name, department, birthday month
    John Smith works in the Accounting department, and was born in November.
    Erica Meyers works in the IT department, and was born in March.
Processed 3 lines.

readerによって返される各行は、区切り文字を削除して見つかったデータを含むString要素のリストです。 返される最初の行には列名が含まれており、特別な方法で処理されます。

csvを使用してCSVファイルを辞書に読み込む

個々のString要素のリストを処理するのではなく、CSVデータを辞書(技術的にはOrdered Dictionary)に直接読み取ることもできます。

ここでも、入力ファイルemployee_birthday.txtは次のとおりです。

name,department,birthday month
John Smith,Accounting,November
Erica Meyers,IT,March

今回は辞書として読み込むためのコードは次のとおりです。

import csv

with open('employee_birthday.txt', mode='r') as csv_file:
    csv_reader = csv.DictReader(csv_file)
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            print(f'Column names are {", ".join(row)}')
            line_count += 1
        print(f'\t{row["name"]} works in the {row["department"]} department, and was born in {row["birthday month"]}.')
        line_count += 1
    print(f'Processed {line_count} lines.')

これにより、以前と同じ出力が得られます。

Column names are name, department, birthday month
    John Smith works in the Accounting department, and was born in November.
    Erica Meyers works in the IT department, and was born in March.
Processed 3 lines.

辞書キーはどこから来たのですか? CSVファイルの最初の行には、辞書の作成に使用するキーが含まれていると想定されています。 これらがCSVファイルにない場合は、fieldnamesオプションパラメータをそれらを含むリストに設定して、独自のキーを指定する必要があります。

オプションのPythonCSVreaderパラメータ

readerオブジェクトは、additional parametersを指定することにより、さまざまなスタイルのCSVファイルを処理できます。その一部を以下に示します。

  • delimiterは、各フィールドを区切るために使用される文字を指定します。 デフォルトはコンマ(',')です。

  • quotecharは、区切り文字を含むフィールドを囲むために使用される文字を指定します。 デフォルトは二重引用符(' " ')です。

  • escapecharは、引用符が使用されていない場合に、区切り文字をエスケープするために使用される文字を指定します。 デフォルトはエスケープ文字なしです。

これらのパラメーターについては、もう少し説明が必要です。 次のemployee_addresses.txtファイルで作業しているとします。

name,address,date joined
john smith,1132 Anywhere Lane Hoboken NJ, 07030,Jan 4
erica meyers,1234 Smith Lane Hoboken NJ, 07030,March 2

このCSVファイルには、nameaddress、およびdate joinedの3つのフィールドが含まれています。これらのフィールドはコンマで区切られています。 問題は、addressフィールドのデータに、郵便番号を示すコンマも含まれていることです。

この状況を処理するには、3つの異なる方法があります。

  • Use a different delimiter
    こうすることで、データ自体でコンマを安全に使用できます。 delimiterオプションのパラメーターを使用して、新しい区切り文字を指定します。

  • Wrap the data in quotes
    選択した区切り文字の特殊な性質は、引用符で囲まれた文字列では無視されます。 したがって、引用符に使用する文字をquotecharオプションパラメーターで指定できます。 その文字もデータに表示されない限り、問題ありません。

  • Escape the delimiter characters in the data
    エスケープ文字は、フォーマット文字列の場合と同じように機能し、エスケープされる文字(この場合は区切り文字)の解釈を無効にします。 エスケープ文字を使用する場合は、escapecharオプションパラメーターを使用して指定する必要があります。

csvでCSVファイルを書き込む

writerオブジェクトと.write_row()メソッドを使用してCSVファイルに書き込むこともできます。

import csv

with open('employee_file.csv', mode='w') as employee_file:
    employee_writer = csv.writer(employee_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)

    employee_writer.writerow(['John Smith', 'Accounting', 'November'])
    employee_writer.writerow(['Erica Meyers', 'IT', 'March'])

quotecharオプションパラメータは、書き込み時にフィールドを引用するために使用する文字をwriterに指示します。 ただし、引用符を使用するかどうかは、quotingのオプションのパラメーターによって決まります。

  • quotingcsv.QUOTE_MINIMALに設定されている場合、.writerow()は、フィールドにdelimiterまたはquotecharが含まれている場合にのみフィールドを引用します。 これはデフォルトのケースです。

  • quotingcsv.QUOTE_ALLに設定されている場合、.writerow()はすべてのフィールドを引用します。

  • quotingcsv.QUOTE_NONNUMERICに設定されている場合、.writerow()はテキストデータを含むすべてのフィールドを引用し、すべての数値フィールドをfloatデータ型に変換します。

  • quotingcsv.QUOTE_NONEに設定されている場合、.writerow()は区切り文字を引用符で囲む代わりにエスケープします。 この場合、escapecharオプションパラメータの値も指定する必要があります。

ファイルをプレーンテキストで読み戻すと、ファイルが次のように作成されていることがわかります。

John Smith,Accounting,November
Erica Meyers,IT,March

csvを使用した辞書からのCSVファイルの書き込み

データを辞書に読み込むことができるので、辞書からもデータを書き出すことができるのは公平なことです。

import csv

with open('employee_file2.csv', mode='w') as csv_file:
    fieldnames = ['emp_name', 'dept', 'birth_month']
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerow({'emp_name': 'John Smith', 'dept': 'Accounting', 'birth_month': 'November'})
    writer.writerow({'emp_name': 'Erica Meyers', 'dept': 'IT', 'birth_month': 'March'})

DictReaderとは異なり、辞書を作成するときはfieldnamesパラメーターが必要です。 これは、考えてみると理にかなっています。fieldnamesのリストがないと、DictWriterは、辞書から値を取得するために使用するキーを知ることができません。 また、fieldnamesのキーを使用して、最初の行を列名として書き出します。

上記のコードは、次の出力ファイルを生成します。

emp_name,dept,birth_month
John Smith,Accounting,November
Erica Meyers,IT,March

pandasライブラリを使用したCSVファイルの解析

もちろん、Python CSVライブラリは町で唯一のゲームではありません。 CSVファイルの読み取りはpandasでも可能です。 分析するデータが多い場合は、強くお勧めします。

pandasは、高性能のデータ分析ツールと使いやすいデータ構造を提供するオープンソースのPythonライブラリです。 pandasはすべてのPythonインストールで使用できますが、Anacondaディストリビューションの重要な部分であり、Jupyter notebooksで非常にうまく機能して、データ、コード、分析結果、視覚化、および説明テキストを共有します。 。

pandasとその依存関係をAnacondaにインストールするのは簡単です。

$ conda install pandas

他のPythonインストールにpip/pipenvを使用している場合:

$ pip install pandas

pandasの動作や使用方法の詳細については、詳しく説明しません。 pandasを使用して大規模なデータセットを読み取って分析する方法の詳細については、working with large Excel files in pandasに関するShantnu Tiwari’sのすばらしい記事をご覧ください。

pandasでCSVファイルを読み取る

pandasのCSV機能の威力を示すために、hrdata.csvと呼ばれるもう少し複雑なファイルを作成しました。 会社の従業員に関するデータが含まれています。

Name,Hire Date,Salary,Sick Days remaining
Graham Chapman,03/15/14,50000.00,10
John Cleese,06/01/15,65000.00,8
Eric Idle,05/12/14,45000.00,10
Terry Jones,11/01/13,70000.00,3
Terry Gilliam,08/12/14,48000.00,7
Michael Palin,05/23/13,66000.00,8

CSVをpandasDataFrameに読み込むのは、すばやく簡単です。

import pandas
df = pandas.read_csv('hrdata.csv')
print(df)

それだけです。3行のコードで、そのうちの1行だけが実際の作業を行っています。 pandas.read_csv()は、提供されたCSVファイルを開き、分析して読み取り、データをDataFrameに保存します。 DataFrameを出力すると、次の出力が得られます。

             Name Hire Date   Salary  Sick Days remaining
0  Graham Chapman  03/15/14  50000.0                   10
1     John Cleese  06/01/15  65000.0                    8
2       Eric Idle  05/12/14  45000.0                   10
3     Terry Jones  11/01/13  70000.0                    3
4   Terry Gilliam  08/12/14  48000.0                    7
5   Michael Palin  05/23/13  66000.0                    8

注目に値するいくつかのポイントを次に示します。

  • まず、pandasは、CSVの最初の行に列名が含まれていることを認識し、それらを自動的に使用しました。 私はこれを善と呼んでいます。

  • ただし、pandasは、DataFrameでゼロベースの整数インデックスも使用しています。 インデックスがどうあるべきかを伝えなかったからです。

  • さらに、列のデータ型を見ると、pandasSalary列とSick Days remaining列を数値に適切に変換していることがわかりますが、Hire Date列はそれでもString。 これは、インタラクティブモードで簡単に確認できます。

    >>>

>>> print(type(df['Hire Date'][0]))

これらの問題に一度に取り組みましょう。 DataFrameインデックスとして別の列を使用するには、index_colオプションパラメータを追加します。

import pandas
df = pandas.read_csv('hrdata.csv', index_col='Name')
print(df)

これで、NameフィールドはDataFrameインデックスになります。

               Hire Date   Salary  Sick Days remaining
Name
Graham Chapman  03/15/14  50000.0                   10
John Cleese     06/01/15  65000.0                    8
Eric Idle       05/12/14  45000.0                   10
Terry Jones     11/01/13  70000.0                    3
Terry Gilliam   08/12/14  48000.0                    7
Michael Palin   05/23/13  66000.0                    8

次に、Hire Dateフィールドのデータ型を修正しましょう。 parse_datesオプションパラメータを使用して、pandasにデータを日付として読み取るように強制できます。これは、日付として扱う列名のリストとして定義されています。

import pandas
df = pandas.read_csv('hrdata.csv', index_col='Name', parse_dates=['Hire Date'])
print(df)

出力の違いに注意してください。

                Hire Date   Salary  Sick Days remaining
Name
Graham Chapman 2014-03-15  50000.0                   10
John Cleese    2015-06-01  65000.0                    8
Eric Idle      2014-05-12  45000.0                   10
Terry Jones    2013-11-01  70000.0                    3
Terry Gilliam  2014-08-12  48000.0                    7
Michael Palin  2013-05-23  66000.0                    8

日付は適切にフォーマットされ、インタラクティブモードで簡単に確認できます。

>>>

>>> print(type(df['Hire Date'][0]))

CSVファイルの最初の行に列名がない場合は、namesオプションパラメーターを使用して列名のリストを提供できます。 最初の行で提供されている列名をオーバーライドする場合にも、これを使用できます。 この場合、header=0オプションパラメータを使用して、既存の列名を無視するようにpandas.read_csv()に指示する必要もあります。

import pandas
df = pandas.read_csv('hrdata.csv',
            index_col='Employee',
            parse_dates=['Hired'],
            header=0,
            names=['Employee', 'Hired','Salary', 'Sick Days'])
print(df)

列名が変更されたため、index_colおよびparse_datesオプションパラメーターで指定された列も変更する必要があることに注意してください。 これにより、次の出力が得られます。

                    Hired   Salary  Sick Days
Employee
Graham Chapman 2014-03-15  50000.0         10
John Cleese    2015-06-01  65000.0          8
Eric Idle      2014-05-12  45000.0         10
Terry Jones    2013-11-01  70000.0          3
Terry Gilliam  2014-08-12  48000.0          7
Michael Palin  2013-05-23  66000.0          8

pandasでCSVファイルを書き込む

もちろん、pandasからデータを再び取得できない場合は、あまり効果がありません。 CSVファイルへのDataFrameの書き込みは、で読み取るのと同じくらい簡単です。 新しい列名でデータを新しいCSVファイルに書き込みましょう。

import pandas
df = pandas.read_csv('hrdata.csv',
            index_col='Employee',
            parse_dates=['Hired'],
            header=0,
            names=['Employee', 'Hired', 'Salary', 'Sick Days'])
df.to_csv('hrdata_modified.csv')

このコードと上記の読み取りコードの唯一の違いは、print(df)呼び出しがdf.to_csv()に置き換えられ、ファイル名が提供されることです。 新しいCSVファイルは次のようになります。

Employee,Hired,Salary,Sick Days
Graham Chapman,2014-03-15,50000.0,10
John Cleese,2015-06-01,65000.0,8
Eric Idle,2014-05-12,45000.0,10
Terry Jones,2013-11-01,70000.0,3
Terry Gilliam,2014-08-12,48000.0,7
Michael Palin,2013-05-23,66000.0,8

結論

CSVファイルの読み取りの基本を理解していれば、データのインポートを処理する必要があるときに足がひっかかりません。 ほとんどのCSVの読み取り、処理、および書き込みタスクは、基本的なcsvPythonライブラリで簡単に処理できます。 読み取りおよび処理するデータが多い場合、pandasライブラリはすばやく簡単なCSV処理機能も提供します。

__ Take the Quiz:インタラクティブな「PythonでのCSVファイルの読み取りと書き込み」クイズで知識をテストします。 完了すると、学習の進捗状況を経時的に追跡できるようにスコアを受け取ります。

テキストファイルを解析する他の方法はありますか? もちろん! ANTLRPLYPlyPlusなどのライブラリはすべて、高負荷の解析を処理できます。単純なString操作が機能しない場合は、常に正規表現があります。

しかし、それらは他の記事のトピックです…