Pandas 連結・結合・計算処理
Pandasの基礎である SeriesとDataFrameの応用として、統計データを連結、結合したり、Numpyの関数に適用したりしてみる。
DataFrameの連結
先ずは、make_random_df() で1から100のランダム値で (カラム:apple orange banana)というSimpleなDataFrameを2つ用意し、それを縦方向と横方向に連結させる。
# DataFrameの連結
import numpy as np
import pandas as pd
def make_random_df(index, columns, seed):
np.random.seed(seed)
df = pd.DataFrame()
for column in columns:
df[column] = np.random.choice(range(1,101), len(index))
#print(df)
df.index = index
return df
columns = ["apple", "orange", "banana"]
df_data1 = make_random_df(range(1,5), columns, 0)
df_data2 = make_random_df(range(1,5), columns, 1)
print(df_data1)
print(df_data2)
print()
print('====================================')
"""
df_data1 とdf_data2 を縦方向に連結する
"""
df1 = pd.concat([df_data1, df_data2], axis=0)
print(df1)
"""
df_data1 とdf_data2 を横方向に連結する
"""
df2 = pd.concat([df_data1, df_data2], axis=1)
print(df2)
""" 実行結果 """
apple orange banana
1 45 68 37
2 48 10 88
3 65 84 71
4 68 22 89
apple orange banana
1 38 76 17
2 13 6 2
3 73 80 77
4 10 65 72
====================================
apple orange banana
1 45 68 37
2 48 10 88
3 65 84 71
4 68 22 89
1 38 76 17
2 13 6 2
3 73 80 77
4 10 65 72
apple orange banana apple orange banana
1 45 68 37 38 76 17
2 48 10 88 13 6 2
3 65 84 71 73 80 77
4 68 22 89 10 65 72
カラム、インデックスが一致しないDataFrameの連結。連結後に該当しない 項目は "NaN"と表示される。
columns1 = ["apple", "orange", "banana"]
columns2 = ["orange", "kiwifruit", "banana"]
df_data1 = make_random_df(range(1,5), columns1, 0)
df_data2 = make_random_df(np.arange(1,8,2), columns2, 1)
print(df_data1)
print(df_data2)
"""
apple orange banana
1 45 68 37
2 48 10 88
3 65 84 71
4 68 22 89
orange kiwifruit banana
1 38 76 17
3 13 6 2
5 73 80 77
7 10 65 72
"""
# df_data1 と df_data2 を縦方向に連結
df1_axis0 = pd.concat([df_data1, df_data2], axis=0)
print(df1_axis0)
""" 実行結果"""
apple banana kiwifruit orange
1 45.0 37 NaN 68
2 48.0 88 NaN 10
3 65.0 71 NaN 84
4 68.0 89 NaN 22
1 NaN 17 76.0 38
3 NaN 2 6.0 13
5 NaN 77 80.0 73
7 NaN 72 65.0 10
# df_data1 と df_data2 を横方向に連結
df1_axis1 = pd.concat([df_data1, df_data2], axis=1)
print(df1_axis1)
""" 実行結果"""
apple orange banana orange kiwifruit banana
1 45.0 68.0 37.0 38.0 76.0 17.0
2 48.0 10.0 88.0 NaN NaN NaN
3 65.0 84.0 71.0 13.0 6.0 2.0
4 68.0 22.0 89.0 NaN NaN NaN
5 NaN NaN NaN 73.0 80.0 77.0
7 NaN NaN NaN 10.0 65.0 72.0
.DataFrame毎に分類(key)させて、横方向に連結させる。以下は X, Y で分けて、さらに、"X" の appleのデータだけ取得する例。
df2_key = pd.concat([df_data1, df_data2], axis=1, keys=["X","Y"])
print(df2_key)
print()
X_apple = df2_key["X", "apple"]
print(X_apple)
""" 実行結果 """
X Y
apple orange banana orange kiwifruit banana
1 45.0 68.0 37.0 38.0 76.0 17.0
2 48.0 10.0 88.0 NaN NaN NaN
3 65.0 84.0 71.0 13.0 6.0 2.0
4 68.0 22.0 89.0 NaN NaN NaN
5 NaN NaN NaN 73.0 80.0 77.0
7 NaN NaN NaN 10.0 65.0 72.0
1 45.0
2 48.0
3 65.0
4 68.0
5 NaN
7 NaN
Name: (X, apple), dtype: float64
DataFrameの結合
次は、DataFrameを結合(merge)させてみよう。
import numpy as np
import pandas as pd
data1 = {"fruits": ["apple", "orange", "banana", "strawberry", "kiwifruit"], "year":[2001,2002,2001,2008,2006],"amount":[1,4,5,6,3]}
df1 = pd.DataFrame(data1)
print(df1)
print()
data2 = {"fruits": ["apple", "orange", "banana", "strawberry", "mango"], "year":[2001,2002,2001,2008,2007],"price":[150,120,100,250,3000]}
df2 = pd.DataFrame(data2)
print(df2)
""" 実行結果 """
amount fruits year
0 1 apple 2001
1 4 orange 2002
2 5 banana 2001
3 6 strawberry 2008
4 3 kiwifruit 2006
fruits price year
0 apple 150 2001
1 orange 120 2002
2 banana 100 2001
3 strawberry 250 2008
4 mango 3000 2007
上記の2つのDataFrameを結合させる。以下は "fruits"をKey 列として内部結合 (= 共通でないものは残さない) させる例。
merge_inner = pd.merge(df1,df2,on="fruits", how="inner")
print(merge_inner)
""" 実行結果 """
amount fruits year_x price year_y
0 1 apple 2001 150 2001
1 4 orange 2002 120 2002
2 5 banana 2001 100 2001
3 6 strawberry 2008 250 2008
以下は "fruits"をKey 列として外部結合 (= 共通でないものも残す) させる例。
merge_outer = pd.merge(df1,df2,on="fruits", how="outer")
print(merge_outer)
""" 実行結果 """
amount fruits year_x price year_y
0 1.0 apple 2001.0 150.0 2001.0
1 4.0 orange 2002.0 120.0 2002.0
2 5.0 banana 2001.0 100.0 2001.0
3 6.0 strawberry 2008.0 250.0 2008.0
4 3.0 kiwifruit 2006.0 NaN NaN
5 NaN mango NaN 3000.0 2007.0
Key列が同名でない場合でも結合はできる。例えば以下のように year と year_id といったように 異なる名前のKey列を持つデータを結合する。
data3 = {"fruits": ["apple", "orange", "banana", "strawberry", "kiwifruit"], "year":[2001,2002,2001,2008,2006],"amount":[1,4,5,6,3]}
df3 = pd.DataFrame(data3)
print(df3)
print()
data4 = {"fruits": ["apple", "orange", "banana", "strawberry", "mango"], "year_id":[2001,2002,2001,2008,2007],"price":[150,120,100,250,3000]}
df4 = pd.DataFrame(data4)
print(df4)
""" 実行結果 """
amount fruits year
0 1 apple 2001
1 4 orange 2002
2 5 banana 2001
3 6 strawberry 2008
4 3 kiwifruit 2006
fruits price year_id
0 apple 150 2001
1 orange 120 2002
2 banana 100 2001
3 strawberry 250 2008
4 mango 3000 2007
""" 第1 DataFrame, 第2 DataFrame, left_on = "year", right_on = "year_id" としてあげる"""
merge_inner2 = pd.merge(df3,df4,left_on="year", right_on="year_id", how="inner")
print(merge_inner2)
""" 実行結果"""
amount fruits_x year fruits_y price year_id
0 1 apple 2001 apple 150 2001
1 1 apple 2001 banana 100 2001
2 5 banana 2001 apple 150 2001
3 5 banana 2001 banana 100 2001
4 4 orange 2002 orange 120 2002
5 6 strawberry 2008 strawberry 250 2008
head() と tail()
最初の数行、最後の数行だけ出力したい場合は、head()、tail()を使う。
df_head = merge_inner2.head(3)
print(df_head)
"""
amount fruits_x year fruits_y price year_id
0 1 apple 2001 apple 150 2001
1 1 apple 2001 banana 100 2001
2 5 banana 2001 apple 150 2001
"""
df_tail = merge_inner2.tail(3)
print(df_tail)
"""
amount fruits_x year fruits_y price year_id
3 5 banana 2001 banana 100 2001
4 4 orange 2002 orange 120 2002
5 6 strawberry 2008 strawberry 250 2008
"""
計算処理
Pandas同士の計算 『+ - * /』が出来ます。また、Numpyの関数に DataFrameを渡すとその全ての要素に対して計算処理をやってくれます。
""" random,seed(0)で DataFrameを作成 """
import numpy as np
import pandas as pd
import math
np.random.seed(0)
columns = ["apple", "orange","banana","strawberry","kiwifruits"]
df = pd.DataFrame()
for column in columns:
df[column] = np.random.choice(range(1,11),10)
df.index = range(1,11)
print(df)
"""
apple orange banana strawberry kiwifruits
1 6 8 6 3 10
2 1 7 10 4 10
3 4 9 9 9 1
4 4 9 10 2 5
5 8 2 5 4 8
6 10 7 4 4 4
7 4 8 1 4 3
8 6 8 4 8 8
9 3 9 6 1 3
10 5 2 1 2 1
"""
##### 以下、計算処理 #####
""" dfの要素を足す """
double_df = df+df #df*2
""" dfの各要素を2乗 """
square_df = df**2
""" 平方根 """
sqrt_df = np.sqrt(df)
print(double_df)
print(square_df)
print(sqrt_df)
""" 実行結果 """
""" double_df """
apple orange banana strawberry kiwifruits
1 12 16 12 6 20
2 2 14 20 8 20
3 8 18 18 18 2
4 8 18 20 4 10
5 16 4 10 8 16
6 20 14 8 8 8
7 8 16 2 8 6
8 12 16 8 16 16
9 6 18 12 2 6
10 10 4 2 4 2
""" square_df """
apple orange banana strawberry kiwifruits
1 36 64 36 9 100
2 1 49 100 16 100
3 16 81 81 81 1
4 16 81 100 4 25
5 64 4 25 16 64
6 100 49 16 16 16
7 16 64 1 16 9
8 36 64 16 64 64
9 9 81 36 1 9
10 25 4 1 4 1
""" sqrt_df """
apple orange banana strawberry kiwifruits
1 2.449490 2.828427 2.449490 1.732051 3.162278
2 1.000000 2.645751 3.162278 2.000000 3.162278
3 2.000000 3.000000 3.000000 3.000000 1.000000
4 2.000000 3.000000 3.162278 1.414214 2.236068
5 2.828427 1.414214 2.236068 2.000000 2.828427
6 3.162278 2.645751 2.000000 2.000000 2.000000
7 2.000000 2.828427 1.000000 2.000000 1.732051
8 2.449490 2.828427 2.000000 2.828427 2.828427
9 1.732051 3.000000 2.449490 1.000000 1.732051
10 2.236068 1.414214 1.000000 1.414214 1.000000
要約統計量
DataFrameの 各要素の平均値、最大値、最小値、などの要約統計量も算出して取り出すことができる。df.describe()
df_des = df.describe()
print(df_des)
print()
""" dfの要約統計量のうち、mean, max,min をとりだす """
df_des_3 = df.describe().loc[{"mean","max","min"}]
print(df_des_3)
""" 実行結果 """
apple orange banana strawberry kiwifruits
count 10.000000 10.000000 10.000000 10.000000 10.000000
mean 5.100000 6.900000 5.600000 4.100000 5.300000
std 2.558211 2.685351 3.306559 2.558211 3.465705
min 1.000000 2.000000 1.000000 1.000000 1.000000
25% 4.000000 7.000000 4.000000 2.250000 3.000000
50% 4.500000 8.000000 5.500000 4.000000 4.500000
75% 6.000000 8.750000 8.250000 4.000000 8.000000
max 10.000000 9.000000 10.000000 9.000000 10.000000
apple orange banana strawberry kiwifruits
min 1.0 2.0 1.0 1.0 1.0
max 10.0 9.0 10.0 9.0 10.0
mean 5.1 6.9 5.6 4.1 5.3
各行の差、各列の差をだしてみる。 df.diff(-/+ X, axis=0/1)
各行の差 正数の場合は前の行と、負の場合は 後の行と比較
""" 2行後との差を計算 """
df_diff_0 = df.diff(-2, axis=0)
print(df_diff_0)
""" 2列後との差を計算 """
df_diff_1 = df.diff(-2, axis=1)
print(df_diff_1)
""" 実行結果 """
apple orange banana strawberry kiwifruits
1 2.0 -1.0 -3.0 -6.0 9.0
2 -3.0 -2.0 0.0 2.0 5.0
3 -4.0 7.0 4.0 5.0 -7.0
4 -6.0 2.0 6.0 -2.0 1.0
5 4.0 -6.0 4.0 0.0 5.0
6 4.0 -1.0 0.0 -4.0 -4.0
7 1.0 -1.0 -5.0 3.0 0.0
8 1.0 6.0 3.0 6.0 7.0
9 NaN NaN NaN NaN NaN
10 NaN NaN NaN NaN NaN
apple orange banana strawberry kiwifruits
1 0.0 5.0 -4.0 NaN NaN
2 -9.0 3.0 0.0 NaN NaN
3 -5.0 0.0 8.0 NaN NaN
4 -6.0 7.0 5.0 NaN NaN
5 3.0 -2.0 -3.0 NaN NaN
6 6.0 3.0 0.0 NaN NaN
7 3.0 4.0 -2.0 NaN NaN
8 2.0 0.0 -4.0 NaN NaN
9 -3.0 8.0 3.0 NaN NaN
10 4.0 0.0 0.0 NaN NaN
Group化
共通カラムをKey に Group化することもできる。以下は Kanto, Kinki, Chubu というRegionで同じ地域にまとめて、そこの平均値を求める処理。
import pandas as pd
prefecture_df = pd.DataFrame([["Tokyo", 2190, 13636,"Kanto"],
["Kanagawa", 2415, 9145, "Kanto"],
["Osaka", 1904, 8837, "Kinki"],
["Kyoto", 4610, 2605, "Kinki"],
["Aichi", 5172, 7505, "Chubu"]],
columns = ["prefecture", "Area", "Population", "Region"])
print(prefecture_df)
""" 出力
prefecture Area Population Region
0 Tokyo 2190 13636 Kanto
1 Kanagawa 2415 9145 Kanto
2 Osaka 1904 8837 Kinki
3 Kyoto 4610 2605 Kinki
4 Aichi 5172 7505 Chubu
"""
""" ReagionでGroup可 """
grouped_region = prefecture_df.groupby("Region")
""" Group可したObjectから平均データ """
mean_df = grouped_region.mean()
print(mean_df)
""" 実行結果
Area Population
Region
Chubu 5172.0 7505.0
Kanto 2302.5 11390.5
Kinki 3257.0 5721.0
"""
これまで Pandas を勉強してきましたが、あるDataFrameに対して非常に多くの処理を簡単に実行することが出来ました。Numpyの計算処理に適用したり、DataFrame同士の差分や加算、累乗なんてのは、機械学習で多く使われるのだろうか。今後の応用が楽しみなところで、次回からは matplotlib を使って、Pythonでグラフを描画していこうと思います。
今回の"note"を気に入って頂けましたら、是非サポートをお願いいたします!