見出し画像

Pandas 連結・結合・計算処理

Pandasの基礎である SeriesDataFrameの応用として、統計データを連結、結合したり、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"を気に入って頂けましたら、是非サポートをお願いいたします!