ここでは、csvファイルの読み込みを説明します。
Pythonを学習していく上でデータインポートは必須であり、print()
文やfor文
を覚えたら、次に知りたいのが、データファイルのインポートのはずです。
#トピック
-
1. pandasでcsvファイルを読み込む:
pd.read_csv()
-
2. pandasで行、列の範囲を指定して csvを読み込む
2.1 日本語を含んだファイルの場合:pd.read_csv(encoding="shift_jis")
2.2 範囲を指定する:pd.read_csv(skiprows=, skipfooter=, usecols=)
-
3. 日付をindexとして読み込む:
pd.read_csv(parse_dates=True)
-
まとめ
ポイント整理 -
参考ページ
https://shilabo.com/python/web_self/
https://note.nkmk.me/python-pandas-read-csv-tsv/
https://qiita.com/sakabe/items/ae1fa47a58c796006627
読み込むファイルは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」とタイプして保存してください。
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=0
はusecols
で切り取った後の、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
を指定する。
#参考ページ
実践で使っている技術が掲載されています。書籍のように構成されています。
ここに掲載したコードが全て掲載されています。
記事内で紹介したページです。