0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Python - Pandas、データフレームを使ったデータ分析

Posted at

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)

スクリーンショット 2023-05-09 182938.png

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?