LoginSignup
1
1

More than 1 year has passed since last update.

1.1. csvファイルを読み込む

Posted at

ここでは、csvファイルの読み込みを説明します。
Pythonを学習していく上でデータインポートは必須であり、print()文やfor文を覚えたら、次に知りたいのが、データファイルのインポートのはずです。

トピック


読み込むファイルはcsv形式(.csv)が好んで用いられます。csvは書式がなく、扱いやすいのです。
Excel(.xlsx)を読み込む事も多いですが、まずはcsv形式を習得する事が重要です。
csvが読み込めれば、Excelもほぼ同じ手順でできます。

後で見るように、Pythonは日本語がひどく苦手です。インポートするデータは英語だけにしておくべきです。

データのインポートが出来ないと、何も出来ないに等しいです。

尚、当サイトではよく使う部分のみを説明し、詳細は他のHPに譲ることにします。
例えば、以下のサイトが非常に役に立ちます。極めて質の高い無料のサイトです。

1. pandasでcsvファイルを読み込む

csvの読み込みは、pandasのpd.read_csv() を使います。

これを使う為に最初にimport pandas as pdと書きます。

読み込んだデータは基本DataFrameとなります。
ここでは、以下のようなcsvファイルを読み込みます。

データはA列が行の名前、B~D列がカラム名(列名)です。
通常、このようにデータには、行の名前(11, 12, 13)と列名(clm1, clm2, clm3)が付いています。列名はヘッダー(header)と呼ばれます。

これを、行の名前が(11, 12, 13)となるように、読み込もうと思います。DataFrameとして読み込んだ、行の名前のことをindexといいます。

以下のリンク(GitHub : 外部サイト)を右クリックして「名前を付けてリンク先を保存」か、一度開いてメモ帳にコピペして保存してください。その際に、拡張子が自動で「.txt」となりますが、「.csv」とタイプして保存してください。

a001_001a.csv

ID,clm1,clm2,clm3
11,1863,7911,2634
12,1850,8000,2623
13,1853,7980,2578

Pythonでは pd.read_csv(‘ファイルのパス’)で読み込みます。
ファイルのパスは、例えば、Windowsのドキュメントに保存した場合、

C:\Users\ユーザ名\Documents

となります。以下はユーザー名が “shilabo” で、ドキュメントフォルダの中に “SHiLABO_python” というフォルダを作った場合です。
パスを指定する場合”r”を頭に書くと\を\と書く必要がなくなり便利です。Windowsのエクスプローラーからパスをコピーして、そのままペーストするだけよくなります。

import pandas as pd
df1a = pd.read_csv(r'C:\users\shilabo\documents\price1_01.csv')
print(df1a)
#   ID  clm1  clm2  clm3
#0  11  1863  7911  2634
#1  12  1850  8000  2623
#2  13  1853  7980  2578

あるいは、パスとファイル名を分けた方がいい場合があります。例えば、ループ(for文)で同じパスの複数のファイルを読み込みたい場合です。
その為、実務では以下のように書くことがあります。

p1 = r'C:\Users\shilabo\Documents\SHiLABO_python'
f1 = 'a001_001a.csv'
p1f1 = p1 +'\\'+f1
df1b = pd.read_csv(p1f1)
print(df1b)
#   ID  clm1  clm2  clm3
#0  11  1863  7911  2634
#1  12  1850  8000  2623
#2  13  1853  7980  2578

結果はどちらも同じです。
ただし、これでは目的が達成されていません。indexが自動で0,1,2と振られ、A列の11, 12, 13はデータとして扱われています。本来はA列の11, 12, 13をindexにしたかったはずです。

そこで、オプションのindex_col=0, header=0を使います。デフォルトはheader=0なので、これは省略できます。

df1c =pd.read_csv(p1f1, index_col=0, header=0)
print(df1c)
#    clm1  clm2  clm3
#ID
#11  1863  7911  2634
#12  1850  8000  2623
#13  1853  7980  2578

indexはカラム名(列名)で指定することもできます。以下は、’clm1’をindexにした場合です。

df1d =pd.read_csv(p1f1, index_col='clm1', header=0)
print(df1d)
#      ID  clm2  clm3
#clm1
#1863  11  7911  2634
#1850  12  8000  2623
#1853  13  7980  2578

2. pandasで行、列の範囲を指定してcsvを読み込む

2.1 日本語を含んだファイルの場合

しかし、現実には、このように元がきれいなデータである事は少なく、多くの場合、次のように、余計なものが含まれています。(GitHubのリンクa001_001b.csvをクリックすると形が見えます)

しかも、日本語の嵐。Pythonは日本語が苦手です。
欲しいのは、セル「B4:E7」の範囲だけです。

部署,金融商品開発部,,,
作成日,2021/3/24,,,
,,,,
,ID,A,B,C
,11,1863,7911,2634
,12,1850,8000,2623
,13,1853,7980,2578
,,,,
*1: Aの参照期間は…。,,,,
*2: Bは〇〇の配当あり。,,,,

これもpandasのpd.read_csv()で読み込みますが、日本語を含む場合、オプションにencoding='shift_jis' を指定します。

“shift”と”jis”の間はアンダースコア(_)であり、ハイフン(-)ではありません。
これを間違い、データが読めないと悩む人が多いです。因みに、他に英語を読み取るencoding = 'utf-8'がありますが、こちらはハイフン(-)です。

とりあずencoding='shift_jis'を指定して実行すると、以下のようになります。

f2 = 'a001_001b.csv'
p1f2 = p1 + '\\' + f2 # p1 = r'C:\Users\shilabo\Documents\SHiLABO_python'
df2a = pd.read_csv(p1f2, encoding='shift_jis') # encoding='shift_jis' が必要
print(df2a)
#               部署    金融商品開発部 Unnamed: 2 Unnamed: 3 Unnamed: 4
#0             作成日  2021/3/24        NaN        NaN        NaN
#1             NaN        NaN        NaN        NaN        NaN
#2             NaN         ID          A          B          C
#3             NaN         11       1863       7911       2634
#4             NaN         12       1850       8000       2623
#5             NaN         13       1853       7980       2578
#6             NaN        NaN        NaN        NaN        NaN
#7   *1: Aの参照期間は…。   NaN        NaN        NaN        NaN
#8  *2: Bは〇〇の配当あり。 NaN        NaN        NaN        NaN

読み込めていますが、csv上で空白も読み込み(NaN)、不必要なデータ(日本語部分)も読み込んでいます。これは意図とは異なります。データだけが必要なのです。むしろ、データ以外は取り込んではいけない、と言った方がいいでしょう。

2.2 範囲を指定する

そこで範囲を指定する為に、以下のオプションを指定します。

skiprows=3 : 最初の3行はスキップ(1~3行目)
skipfooter=3 : 下から3行はスキップ(8~10行目)
usecols=range(1,5) : 列の指定(Python上での1列~4列目 = csv上では2列目(B列)から5列目(F列))

skipfooter=でWarningが出た場合、更にオプションで engine='python'を指定します。

ここで、usecols=について説明します。

range(1,5)と書くと、0始まりのPythonから見て、1, 2, 3, 4列目となります。
つまり0列目はスキップし、1, 2, 3, 4列目を読み、5列目は含みません。
csv上では普通1, 2, 3…列と数えるし、終わりの5も含むか含まないか、この感覚が難しいです。
実際には、print()で意図通りか必ず確認します。

また、index_col=0usecolsで切り取った後の、Pythonの0列目をindexにする、という意味です。
同様に、header=0は、skiprowsで切り取った後の、Pythonの0行目をヘッダーにする、という意味です。

Pythonは基本0で始まります(1ではない)。

df2b= pd.read_csv(p1f2, encoding='shift_jis', skiprows=3, skipfooter=3, usecols=range(1,5), index_col=0, header=0, engine='python') #engine='python'で実行できる #
print(df2b)
#       A     B     C
#ID
#11  1863  7911  2634
#12  1850  8000  2623
#13  1853  7980  2578

usecols の範囲はリストで指定することもできます。
この例の場合、usecols=[1,2,3,4]。ここでも、0始まりを意識しましょう。

df2c= pd.read_csv(p1f2, encoding='shift_jis', skiprows=3, skipfooter=3, usecols=[1,2,3,4], index_col=0, header=0, engine='python')
print(df2c)
#       A     B     C
#ID
#11  1863  7911  2634
#12  1850  8000  2623
#13  1853  7980  2578

3. 日付をindexとして読み込む

日付がある時系列データを読み込む場合、”型”をdatetime型として読み込むと便利です。

index_col=でindexとするカラム名(列名)を指定し、parse_dates=Trueのオプションを指定します。

以下のcsvファイルを読み込んでみます。(GitHubのa001_001c.csvのリンクをクリックすると形が見えます。)

ValDate,clm1,clm2,clm3
1999/1/1,1863,7911,2634
1999/2/12,1850,8000,2623
1999/3/23,1853,7980,2578
2005/1/23,1858,7905,2578
2005/2/12,1873,7952,2578
2005/3/1,1844,7820,2599
2021/1/12,1820,7480,2556
2021/2/23,1885,7349,2557
2021/3/1,1879,7199,2569
f3 = 'a001_001c.csv'
p1f3 = p1 + '\\' +f3 #p1 =r'C:\Users\shilabo\Documents\SHiLABO_python'
df3 = pd.read_csv(p1f3, index_col='ValDate',parse_dates=True)
print(df3)
#            clm1  clm2  clm3
#ValDate
#1999-01-01  1863  7911  2634
#1999-02-12  1850  8000  2623
#1999-03-23  1853  7980  2578
#2005-01-23  1858  7905  2578
#2005-02-12  1873  7952  2578
#2005-03-01  1844  7820  2599
#2021-01-12  1820  7480  2556
#2021-02-23  1885  7349  2557
#2021-03-01  1879  7199  2569

indexをdatetime型にすると、df.index.year == , df.index.month == , df.index.day ==と書くことで、年、月、日でフィルターをかけることができます。
以下は、1999年だけ、2月だけ、23日だけ、の例です。

print(df3[df3.index.year == 1999])
#            clm1  clm2  clm3
#ValDate
#1999-01-01  1863  7911  2634
#1999-02-12  1850  8000  2623
#1999-03-23  1853  7980  2578

print(df3[df3.index.month == 2])
#            clm1  clm2  clm3
#ValDate
#1999-02-12  1850  8000  2623
#2005-02-12  1873  7952  2578
#2021-02-23  1885  7349  2557

print(df3[df3.index.day == 23])
#            clm1  clm2  clm3
#ValDate
#1999-03-23  1853  7980  2578
#2005-01-23  1858  7905  2578
#2021-02-23  1885  7349  2557

年、年月の指定ならば、以下のようにdf['1999']df['2021-02']でも可能です。

print(df3['1999'])
#             clm1  clm2  clm3
#ValDate
#1999-01-01  1863  7911  2634
#1999-02-12  1850  8000  2623
#1999-03-23  1853  7980  2578
print(df3['2021-02'])
#             clm1  clm2  clm3
#ValDate
#2021-02-23  1885  7349  2557

indexをdatetime型にした場合の使い方は、次のサイトが詳しいです。

まとめ

pd.read_csv()にいくつもオプションを指定すれば、不要なものを含むcsvファイルもデータとして読み込めます。しかし、とても面倒です。
現実には難しいですが、出来れば、読み込むcsvファイルの不要部分を削除し、シンプルなデータ形式にしておくのがいいです。その方が時間が省略できます

また、日本語が含まれると、エラーの原因になり、その解決に時間が掛かるので、可能ならば日本語は避けた方がいいです。

ポイント整理

  • pd.read_csv()を使う。
  • 日本語を含む場合、encoding='shift_jis'をオプションに指定する。
  • skiprows=, skipfooter=で上下の範囲(行)を指定できる。
  • skipfooter=でエラーが出たらengine='python'を指定する。
  • usecols=で左右(列)の範囲を指定できる。
  • index_col=でindexにする列を指定できる。
  • indexをdatetime型で読み込む場合、parse_dates=Trueを指定する。

参考ページ

実践で使っている技術が掲載されています。書籍のように構成されています。

ここに掲載したコードが全て掲載されています。

記事内で紹介したページです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1