Odyssey CBTのPython3 エンジニア認定データ分析試験の学習を始めました。今回はPandasを使ったデータ処理について学習しました。
https://pandas.pydata.org/docs/user_guide/index.html
Pandasについて
PandasはNumpyを基盤に1次元データを扱うSeries型
、2次元データを扱うDataFrame型
を提供するライブラリーです。DataFrameを用いるとTidyverseを使ったR言語環境のように、データ分析のフレームワークを使った便利機能を色々使うことができます。(大雑把)
import numpy as np
import pandas as pd
# Series型
series = pd.Series([10,20,30,40,50])
print(series)
0 10
1 20
2 30
3 40
4 50
dtype: int64
# DataFrame型
df = pd.DataFrame([[10,"a",True],[20,"b",False],[30,"c",False],[40,"d",True]])
df
0 1 2
0 10 a True
1 20 b False
2 30 c False
3 40 d True
arrange, reshape - データの作成と変形変形
DataFrame型はNumpyと同様、データ型であるndarray型を生成・変形することでデータの内容や行列方向の形状を変更できます。
# reshape - データを作成・変形してDataFrame型にする
df = pd.DataFrame(np.arange(100).reshape((25, 4)))
print(df)
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
4 16 17 18 19
5 20 21 22 23
6 24 25 26 27
7 28 29 30 31
8 32 33 34 35
9 36 37 38 39
10 40 41 42 43
11 44 45 46 47
12 48 49 50 51
13 52 53 54 55
14 56 57 58 59
15 60 61 62 63
16 64 65 66 67
17 68 69 70 71
18 72 73 74 75
19 76 77 78 79
20 80 81 82 83
21 84 85 86 87
22 88 89 90 91
23 92 93 94 95
24 96 97 98 99
head, tail, shape -データの先頭・後方、形状を確認
データの先頭・後方5列を確認するにはhead
, tail
というメソッドを使うことができます。shape
では形状の確認ができます。
df.head()
df.tail()
df.shape
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
4 16 17 18 19
0 1 2 3
20 80 81 82 83
21 84 85 86 87
22 88 89 90 91
23 92 93 94 95
24 96 97 98 99
(25, 4)
コラム名・インデックス名を指定・参照
# コラム名・インデックス名を指定・参照
dframe = pd.DataFrame(np.arange(12).reshape((4,3)), columns=["A","B","C"], index=["01","02","03","04"])
print(dframe)
A B C
01 0 1 2
02 3 4 5
03 6 7 8
04 9 10 11
# コラム名・インデックス名を指定すると参照できる
dframe["A"]
dframe[["A", "B"]]
01 0
02 3
03 6
04 9
Name: A, dtype: int64
A B
01 0 1
02 3 4
03 6 7
04 9 10
# インデックスを使った参照 - 最初の3行をスライスする
dframe[:3]
A B C
01 0 1 2
02 3 4 5
03 6 7 8
read_csv, read_excel - データの読み込み
Pandasではcsv・excel形式のファイルを読み込んでデータフレームにすることができます。サンプルデータとして「Pythonによるあたらしいデータ分析の教科書 第2版」のデータを使います。
import pandas as pd
df = pd.read_csv("202204health.csv", encoding="utf-8")
df.head()
日付 歩数 摂取カロリー
0 2022-04-01 5439 2500
1 2022-04-02 2510 2300
2 2022-04-03 10238 1950
3 2022-04-04 8209 1850
4 2022-04-05 9434 1930
df = pd.read_excel("202204health.xlsx")
df.head()
日付 歩数 摂取カロリー
0 2022-04-01 5439 2500
1 2022-04-02 2510 2300
2 2022-04-03 10238 1950
3 2022-04-04 8209 1850
4 2022-04-05 9434 1930
read_html - WebサイトのHTML要素をスクレイピングする
urlの直接指定とread_html
メソッドを組み合わせると簡単なWebスクレイピングを行う事ができます。
url = "https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%83%E3%83%97%E3%83%AC%E3%83%99%E3%83%AB%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E4%B8%80%E8%A6%A7"
tables = pd.read_html(url, flavor = "html5lib")
len(tables)
#国別のテーブルはインデックスの4番目に入っている
df=tables[4]
df
Name Entity Explanation Notes IDN DNSSEC SLD IPv6
0 .ac アセンション島 NaN 広く学術的なサイト(大学など)のために用いられる。アセンション島はイギリス領であるが、イギリ... Yes Yes Yes Yes
1 .ad アンドラ NaN アンドラにおける商標または市民権が必要となる[7][8]。 NaN Yes Yes NaN
2 .ae アラブ首長国連邦 NaN NaN NaN No Yes NaN
3 .af アフガニスタン NaN NaN NaN Yes Yes NaN
4 .ag アンティグア・バーブーダ NaN AGがドイツの株式会社(Aktiengesellschaft)の略称であることから、非公式に... NaN Yes Yes NaN
... ... ... ... ... ... ... ... ...
248 .ye イエメン NaN NaN NaN No No NaN
249 .yt マヨット島 NaN 欧州連合・スイス・ノルウェー・アイスランド・リヒテンシュタインの個人・企業に限る[cctld... Yes[cctld 12] Yes Yes NaN
250 .za 南アフリカ Zuid-Afrika (オランダ語) NaN NaN No No NaN
251 .zm ザンビア NaN NaN NaN Yes Yes[cctld 28] NaN
252 .zw ジンバブエ NaN NaN NaN No No NaN
253 rows × 8 columns
to_csv, to_excel, to_pickle - データをcsv・excel・DataFrameとして出力する
#データをcsv・excelとして出力する
df.to_csv("data/write_data.csv")
df.to_excel("data/write_data.xlsx")
#DataFrame形式で出力→次回利用時にそのままデータフレームとして使用できる
df.to_pickle("data/write_df.pickle")
df = pd.read_pickle("data/write_df.pickle")
データの条件抽出
if文のように条件分岐を行う事で、特定の条件を満たすデータか否かをbool型
で判定できます。また、条件に合致するデータのみを別のデータフレームに代入することができます。
df = pd.read_excel("202204health.xlsx")
df.loc[:, "歩数"] >= 10000
0 False
1 False
2 True
3 False
4 False
5 False
6 False
7 False
8 True
9 False
10 False
11 False
12 True
13 False
14 False
15 False
16 False
17 False
18 False
19 True
20 True
21 False
22 False
23 False
24 False
25 False
26 False
27 False
28 False
29 False
Name: 歩数, dtype: bool
#条件で抽出→別のデータフレームを作成する
df_selected = df.loc[df.loc[:, "歩数"] >= 10000,:]
df_selected
日付 歩数 摂取カロリー
2 2022-04-03 10238 1950
8 2022-04-09 12045 1950
12 2022-04-13 10287 1800
19 2022-04-20 15328 1800
20 2022-04-21 12849 1940
データの整形・前処理
日付データ等はobject型
となっていることが多いので、to_datetime
メソッドで日付型に整形します。
その他細かい修正として、摂取カロリーなどの連続値をint型からfloat型に変換します。
#データフレームの方式を確認する
df.dtypes
日付 object
歩数 int64
摂取カロリー int64
dtype: object
#日付データはobject型になっていることが多いので、to_datetimeメソッドで日付型にする
df.loc[:, "date"]=df.loc[:,"日付"].apply(pd.to_datetime)
df.loc[:, "date"]
<bound method NDFrame.head of 0 2022-04-01
1 2022-04-02
2 2022-04-03
3 2022-04-04
4 2022-04-05
5 2022-04-06
6 2022-04-07
7 2022-04-08
8 2022-04-09
9 2022-04-10
10 2022-04-11
11 2022-04-12
12 2022-04-13
13 2022-04-14
14 2022-04-15
15 2022-04-16
16 2022-04-17
17 2022-04-18
18 2022-04-19
19 2022-04-20
20 2022-04-21
21 2022-04-22
22 2022-04-23
23 2022-04-24
24 2022-04-25
25 2022-04-26
26 2022-04-27
27 2022-04-28
28 2022-04-29
29 2022-04-30
Name: date, dtype: datetime64[ns]>
#摂取カロリーをintからfloat型にする。データの型の微妙な違いに気を付ける
df.loc[:, "摂取カロリー"]=df.loc[:, "摂取カロリー"].astype(np.float32)
df.head()
日付 歩数 摂取カロリー date
date
2022-04-01 2022-04-01 5439 2500.0 2022-04-01
2022-04-02 2022-04-02 2510 2300.0 2022-04-02
2022-04-03 2022-04-03 10238 1950.0 2022-04-03
2022-04-04 2022-04-04 8209 1850.0 2022-04-04
2022-04-05 2022-04-05 9434 1930.0 2022-04-05
ソート - ort_valuesメソッドで並べ替え
int・float型はsort_valuesメソッドで並べ替えができます。
df.sort_values(by="歩数").head()
日付 歩数 摂取カロリー date
1 2022-04-02 2510 2300 2022-04-02
22 2022-04-23 3890 1950 2022-04-23
21 2022-04-22 4029 2300 2022-04-22
29 2022-04-30 4093 1950 2022-04-30
7 2022-04-08 4873 2300 2022-04-08
#並べ替え - int・float型を降順で並べ替える
df.sort_values(by="歩数", ascending=False).head()
日付 歩数 摂取カロリー date
date
2022-04-20 2022-04-20 15328 1800.0 2022-04-20
2022-04-21 2022-04-21 12849 1940.0 2022-04-21
2022-04-09 2022-04-09 12045 1950.0 2022-04-09
2022-04-13 2022-04-13 10287 1800.0 2022-04-13
2022-04-03 2022-04-03 10238 1950.0 2022-04-03
drop - 不要カラムの削除
日付
とdate
でデータ内容が重複しているので、変換前の日付
を削除します。
# 日付とdateでデータ内容が重複しているので、`drop`メソッドで変換前の"日付"を削除する
df = df.drop("日付", axis=1)
df.head()
歩数 摂取カロリー date
0 5439 2500 2022-04-01
1 2510 2300 2022-04-02
2 10238 1950 2022-04-03
3 8209 1850 2022-04-04
4 9434 1930 2022-04-05
計算結果の挿入
歩数当たりのカロリーをデータフレームに挿入します。
df.loc[:,"歩数/カロリー"] = (df.loc[:, "歩数"]/df.loc[:, "摂取カロリー"])
df
歩数 摂取カロリー date 歩数/カロリー
0 5439 2500.0 2022-04-01 2.175600
1 2510 2300.0 2022-04-02 1.091304
2 10238 1950.0 2022-04-03 5.250256
3 8209 1850.0 2022-04-04 4.437297
4 9434 1930.0 2022-04-05 4.888083
5 7593 1800.0 2022-04-06 4.218333
.
.
.
計算の関数化
数/カロリーをもとに運動指数を関数で作成します
##計算の関数化 - 歩数/カロリーをもとに運動指数を関数で作成する
def exercise_judge(ex):
if ex <= 3.0:
return "Low"
elif 3.0 < ex <= 6.0:
return "Mid"
else:
return "High"
df.loc[:,"運動指数"] = df.loc[:, "歩数/カロリー"].apply(exercise_judge)
df
歩数 摂取カロリー date 歩数/カロリー 運動指数
0 5439 2500.0 2022-04-01 2.175600 Low
1 2510 2300.0 2022-04-02 1.091304 Low
2 10238 1950.0 2022-04-03 5.250256 Mid
3 8209 1850.0 2022-04-04 4.437297 Mid
4 9434 1930.0 2022-04-05 4.888083 Mid
5 7593 1800.0 2022-04-06 4.218333 Mid
.
.
.
#ワンホットベクトル化
#定性データをワンホットベクトルを使ったデータに変換することができます。教師あり学習などの機械学習に利用するデータにしたい時に役立ちます。
#get_dummies - 定性データをワンホットベクトルを使ったデータに変換する
df_moved = pd.get_dummies(df.loc[:,"運動指数"], prefix="運動")
df_moved
運動_High 運動_Low 運動_Mid
0 0 1 0
1 0 1 0
2 0 0 1
3 0 0 1
4 0 0 1
5 0 0 1
.
.
.
時系列データを生成
時系列データを作成したい時等に、必要な分の日付の配列を開始・終了日を指定して作成することができます。
import pandas as pd
import numpy as np
# 1ヶ月分の日付の配列を開始・終了日を指定して作成する
dates = pd.date_range(start="2022-04-01", end="2022-04-30")
dates
DatetimeIndex(['2022-04-01', '2022-04-02', '2022-04-03', '2022-04-04',
'2022-04-05', '2022-04-06', '2022-04-07', '2022-04-08',
'2022-04-09', '2022-04-10', '2022-04-11', '2022-04-12',
'2022-04-13', '2022-04-14', '2022-04-15', '2022-04-16',
'2022-04-17', '2022-04-18', '2022-04-19', '2022-04-20',
'2022-04-21', '2022-04-22', '2022-04-23', '2022-04-24',
'2022-04-25', '2022-04-26', '2022-04-27', '2022-04-28',
'2022-04-29', '2022-04-30'],
dtype='datetime64[ns]', freq='D')
作成した日付をインデックスにすることができます。
#作成した日付をインデックスにし、対応する値を乱数にする
mg = np.random.default_rng(123)
df = pd.DataFrame(mg.integers(1,31,size=30),index=dates,columns=["乱数値"])
df
乱数値
2022-04-01 1
2022-04-02 21
2022-04-03 18
2022-04-04 2
2022-04-05 28
2022-04-06 7
.
.
.
1年の日付の配列を作成
# 1年の日付の配列を作成する
dates = pd.date_range(start="2022-01-01", periods=365)
dates
DatetimeIndex(['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04',
'2022-01-05', '2022-01-06', '2022-01-07', '2022-01-08',
'2022-01-09', '2022-01-10',
...
'2022-12-22', '2022-12-23', '2022-12-24', '2022-12-25',
'2022-12-26', '2022-12-27', '2022-12-28', '2022-12-29',
'2022-12-30', '2022-12-31'],
dtype='datetime64[ns]', length=365, freq='D')
#作成した日付をインデックスにし、対応する値を乱数にする
mg = np.random.default_rng(123)
df = pd.DataFrame(mg.integers(1,31,size=365),index=dates,columns=["乱数値"])
df
乱数値
2022-01-01 1
2022-01-02 21
2022-01-03 18
2022-01-04 2
2022-01-05 28
... ...
2022-12-27 23
2022-12-28 17
2022-12-29 2
2022-12-30 7
2022-12-31 23
月平均のデータフレームを作成
# Grouperを使うと月ごと・週ごとの平均などが出力できる
df.groupby(pd.Grouper(freq="M")).mean()
乱数値
2022-01-31 14.516129
2022-02-28 12.892857
2022-03-31 16.935484
2022-04-30 12.933333
2022-05-31 16.612903
2022-06-30 14.200000
2022-07-31 14.161290
2022-08-31 15.935484
2022-09-30 13.500000
2022-10-31 13.483871
2022-11-30 14.300000
2022-12-31 17.741935
欠損値の処理
ミスや計測値がない場合、データ型にNaN
型(欠損値)が挿入されていることがあります。これらの値・行列を削除する方法・値を埋め合わせる方法を考えます。
#欠損値-NaNを処理する方法を覚える
import numpy as np
import pandas as pd
df_202205 = pd.read_csv("202205health.csv", encoding="utf-8", index_col="日付", parse_dates=True)
df_202205
歩数 摂取カロリー
日付
2022-05-01 1439.0 4500.0
2022-05-02 8120.0 2420.0
2022-05-03 NaN NaN
2022-05-04 2329.0 1500.0
2022-05-05 NaN NaN
2022-05-06 3233.0 1800.0
.
.
.
dropna - 欠損値を含む行を削除
df_202205_dropped = df_202205.dropna()
df_202205_dropped
歩数 摂取カロリー
日付
2022-05-01 1439.0 4500.0
2022-05-02 8120.0 2420.0
2022-05-04 2329.0 1500.0
2022-05-06 3233.0 1800.0
2022-05-07 9593.0 2200.0
2022-05-08 9213.0 1800.0
2022-05-09 5593.0 2500.0
# fillna - 欠損値を含む行に値を挿入する
df_202205_filled = df_202205.fillna(0)
df_202205_filled
歩数 摂取カロリー
日付
2022-05-01 1439.0 4500.0
2022-05-02 8120.0 2420.0
2022-05-03 0.0 0.0
2022-05-04 2329.0 1500.0
2022-05-05 0.0 0.0
2022-05-06 3233.0 1800.0
2022-05-07 9593.0 2200.0
2022-05-08 9213.0 1800.0
2022-05-09 5593.0 2500.0
# fillna, method = "ffill",値を前の行で保管する
df_202205_fill = df_202205.fillna(method = "ffill")
df_202205_fill
歩数 摂取カロリー
日付
2022-05-01 1439.0 4500.0
2022-05-02 8120.0 2420.0
2022-05-03 8120.0 2420.0
2022-05-04 2329.0 1500.0
2022-05-05 2329.0 1500.0
2022-05-06 3233.0 1800.0
2022-05-07 9593.0 2200.0
2022-05-08 9213.0 1800.0
2022-05-09 5593.0 2500.0
# 平均値、中央値、最頻値で保管する
# mean-平均、median-中央値、mode().iloc[0,:]-最頻値
df_202205_fillmean = df_202205.fillna(df_202205.mean())
df_202205_fillmean
歩数 摂取カロリー
日付
2022-05-01 1439.000000 4500.000000
2022-05-02 8120.000000 2420.000000
2022-05-03 5645.714286 2388.571429
2022-05-04 2329.000000 1500.000000
2022-05-05 5645.714286 2388.571429
2022-05-06 3233.000000 1800.000000
2022-05-07 9593.000000 2200.000000
2022-05-08 9213.000000 1800.000000
2022-05-09 5593.000000 2500.000000
統計量を表示
import numpy as np
import pandas as pd
df = pd.read_excel("202204health.xlsx")
#最頻値
df.loc[:, "摂取カロリー"].mode()
#平均値
df.loc[:, "摂取カロリー"].mean()
中央値
df.loc[:, "摂取カロリー"].median()
#標準偏差(母分散)
df.loc[:, "摂取カロリー"].std()
#標準偏差(標本分散)
df.loc[:, "摂取カロリー"].std(ddof=0)
#要約統計量をまとめて表示
df.describe()
0 2300
Name: 摂取カロリー, dtype: int64
2026.6666666666667
1945.0
205.54944590692452
202.09458731549992
歩数 摂取カロリー
count 30.000000 30.000000
mean 7766.366667 2026.666667
std 2689.269308 205.549446
min 2510.000000 1800.000000
25% 6661.500000 1870.000000
50% 7561.000000 1945.000000
75% 8408.500000 2300.000000
max 15328.000000 2500.000000
df.loc[:,"歩数/カロリー"] = (df.loc[:, "歩数"]/df.loc[:, "摂取カロリー"])
df
日付 歩数 摂取カロリー 歩数/カロリー
0 2022-04-01 5439 2500 2.175600
1 2022-04-02 2510 2300 1.091304
2 2022-04-03 10238 1950 5.250256
3 2022-04-04 8209 1850 4.437297
4 2022-04-05 9434 1930 4.888083
5 2022-04-06 7593 1800 4.218333
6 2022-04-07 9320 1940 4.804124
.
.
.
#相関係数 - カラム間のデータの相関係数を確認する
df.corr()
歩数 摂取カロリー 歩数/カロリー
歩数 1.000000 -0.498703 0.982828
摂取カロリー -0.498703 1.000000 -0.636438
歩数/カロリー 0.982828 -0.636438 1.000000
#散布図行列 - カラム間のデータの分布を表示する
from pandas.plotting import scatter_matrix
plot=scatter_matrix(df)