Japan
サイト内の現在位置
FrovedisのDataFrameを使ったデータ操作
no.0112021.5.31 今回はFrovedisのDataFrameを使用した操作についてご紹介します。
データ分析に際しては、様々なデータ蓄積場所、例えばCSVファイルのような小規模データファイル、構造型・非構造型データベース、Spark、Hadoopといった大規模なデータ保管場所などから必要なデータを取り込み、何らかの前処理を実施します。Pythonではデータの取り込み先として、標準ライブラリが持つList, Dictionary, Tupleなどのデータ形式を選択することができますし、データコンテナとしての柔軟な操作機能を有するNumpyやpandasを使用することも考えられます。
これらの中で、pandasはラベル付けされたデータ構造、データ整形のための機能をデータ分析者に提供します。pandasを使用して複数テーブルのマージ、データの集約、スライシングを実施した後に、データの統計的情報を確認することやデータ分析アルゴリズムを使った分析に進むことが可能です。ListやDictionary形式に収められたデータを扱うためには大なり小なり処理コードを作る必要に迫られますが、pandasを使うと多くのことをDataFrameが持つ機能を使って実現できます。また多くの場合に当てはまることですが、loop処理によってListやDictionary形式のデータに何らかの変更を加えるより、Numpyのユニバーサル関数やpandasのメソッドを使用するほうがより高速に実施できます。また、大規模なデータになるほどその差は広がります。
本コラム第9回でFrovedisがSparkの分散メモリ上のデータを使用したデータ分析をSX-Aurora TSUBASAにオフロードできることを書きました。そこまで大規模なデータを扱わない場合はpandasのDataFrameでデータを取り込み、FrovedisのDataFrameに変換します。これに伴いデータはx86からSX-Aurora TSUBASAのVector Engineのメモリへ転送されます。そのうえで前処理しFrovedisで分析処理することが可能です。
FrovedisのDataFrameが提供する機能はpandas版のサブセットに相当します。Select、Join、Sort、Groupbyといった操作機能を提供するほか、pandas DataFrameとの間でデータを受け渡しする関数を使用することができます。必要に応じてNumpyの多次元配列オブジェクトを用いた数学的演算処理やpandasの時系列データの取り扱い、データ入出力機能と連携することで、柔軟なデータ整形を実施します。
以下、Jupyter notebookを使用しながらFrovedis DataFrameの操作例を見ていきます。
初めに小規模な架空データを使い、select、sort、groupby等によるデータ操作を実行します。
サンプルデータを使用したFrovedis DataFrame操作例¶
import os
import numpy as np
import pandas as pd
from frovedis.exrpc.server import FrovedisServer
from frovedis.dataframe.df import FrovedisDataframe
Frovedis serverを起動します。¶
FrovedisServer.initialize("mpirun -np 2 {}".format(os.environ['FROVEDIS_SERVER']))
'[ID: 1] FrovedisServer (Hostname: handson02, Port: 42383) has been initialized with 2 MPI processes.'
2種類のサンプルデータを辞書形式で用意した後にpandas DataFrameを経由しFrovedis DataFrameへ変換します。pandasからFrrovedisのDataFrameに変換される際にデータがSX-Aurora TSUBASAのメモリに転送されます。¶
peopleDF = {
'Ename' : ['Michael', 'Andy', 'Tanaka', 'Raul', 'Yuta'],
'Age' : [29, 30, 27, 19, 31],
'Country' : ['USA', 'England', 'Japan', 'France', 'Japan']
}
countryDF = {
'Ccode' : [1, 2, 3, 4],
'Country' : ['USA', 'England', 'Japan', 'France']
}
pdf1 = pd.DataFrame(peopleDF)
pdf2 = pd.DataFrame(countryDF)
fdf1 = FrovedisDataframe(pdf1)
fdf2 = FrovedisDataframe(pdf2)
Frovedis DataFrameを表示します。¶
# display created frovedis dataframes
print ("* print Frovedis DataFrame")
print(fdf1.to_pandas_dataframe())
print(fdf2.to_pandas_dataframe())
* print Frovedis DataFrame Ename Age Country index 0 Michael 29 USA 1 Andy 30 England 2 Tanaka 27 Japan 3 Raul 19 France 4 Yuta 31 Japan Ccode Country index 0 1 USA 1 2 England 2 3 Japan 3 4 France
column名を指定し列を選択します。¶
# select demo
print ("* select Ename and Age")
print(fdf1[["Ename","Age"]].to_pandas_dataframe())
* select Ename and Age Ename Age 0 Michael 29 1 Andy 30 2 Tanaka 27 3 Raul 19 4 Yuta 31
"年齢"、"国名"を指定したフィルタリングを実施します。¶
# filter demo
print ("* filter by Age > 19 and Contry == 'Japan'")
print(fdf1[fdf1.Age > 19 and fdf1.Country == 'Japan'].to_pandas_dataframe())
* filter by Age > 19 and Contry == 'Japan' Ename Age Country 0 Tanaka 27 Japan 1 Yuta 31 Japan
"年齢"でソートします。¶
# sort demo
print ("* sort by Age (descending order)")
print(fdf1.sort("Age",ascending=False).to_pandas_dataframe()) # single column, descending
* sort by Age (descending order) Ename Age Country 0 Yuta 31 Japan 1 Andy 30 England 2 Michael 29 USA 3 Tanaka 27 Japan 4 Raul 19 France
複数のColumnを指定してソートします。¶
print ("* sort by Country and Age")
print(fdf1.sort(["Country", "Age"]).to_pandas_dataframe()) # multiple column
* sort by Country and Age Ename Age Country 0 Andy 30 England 1 Raul 19 France 2 Tanaka 27 Japan 3 Yuta 31 Japan 4 Michael 29 USA
"国名"によるグループ分けを実施後、各グループにおける年齢の最大値、最小値、平均値を集計します。¶
# groupby demo
print ("* groupby Country and max/min/mean of Age and count of Ename")
out = fdf1.groupby('Country')
out = out.agg({'Age': ['max','min','mean']})
out2 = out[["Country","max_Age","min_Age","mean_Age"]]
print(out2.to_pandas_dataframe())
* groupby Country and max/min/mean of Age and count of Ename Country max_Age min_Age mean_Age 0 England 30 30 30.0 1 Japan 31 27 29.0 2 France 19 19 19.0 3 USA 29 29 29.0
column名を変更します。¶
# renaming demo
print ("* rename Contry to Cname")
fdf3 = fdf2.rename({'Country' : 'Cname'})
print(fdf3.to_pandas_dataframe())
* rename Contry to Cname Ccode Cname index 0 1 USA 1 2 England 2 3 Japan 3 4 France
column名を指定し2つのDataFrameを統合します。¶
# join after column renaming
print ("* merge (join) two tables")
out = fdf1.merge(fdf3, left_on="Country", right_on="Cname") # with defaults
print(out.to_pandas_dataframe())
* merge (join) two tables Ename Age Country Ccode Cname index 0 Michael 29 USA 1 USA 1 Andy 30 England 2 England 2 Tanaka 27 Japan 3 Japan 3 Raul 19 France 4 France 4 Yuta 31 Japan 3 Japan
2つのDataFrameの統合、ソートを実施後、selectした結果を表示します。¶
# operation chaining: join -> sort -> select -> show
print ("* chaining: merge two tables, sort by Age, and select Age, Ename and Country")
out = fdf1.merge(fdf3, left_on="Country", right_on="Cname") \
.sort("Age")[["Age", "Ename", "Country"]]
print(out.to_pandas_dataframe())
* chaining: merge two tables, sort by Age, and select Age, Ename and Country Age Ename Country 0 19 Raul France 1 27 Tanaka Japan 2 29 Michael USA 3 30 Andy England 4 31 Yuta Japan
DataFrame内データの統計情報を表示します。¶
# column statistics
print ("describe: ")
print (fdf1.describe())
print ("\n")
describe: Age count 5.000000 mean 27.200000 std 4.816638 sum 136.000000 min 19.000000 max 31.000000
PandasのDataFrameとFrovedis DataFrameを統合して新たなFrovedis DataFrame "joined"を作成します。¶
# merging with panda dataframe
print ("* merge with pandas table")
pdf2.rename(columns={'Country' : 'Cname'},inplace=True)
joined = fdf1.merge(pdf2, left_on="Country", right_on="Cname")
print(joined.to_pandas_dataframe())
* merge with pandas table Ename Age Country Ccode Cname index 0 Michael 29 USA 1 USA 1 Andy 30 England 2 England 2 Tanaka 27 Japan 3 Japan 3 Raul 19 France 4 France 4 Yuta 31 Japan 3 Japan
Frovedis DataFrameをPandas DataFrameに変換します。¶
# conversion
print ("* convert Frovedis DataFrame to Pandas DataFrame")
print (fdf1.to_pandas_dataframe())
print ("\n")
* convert Frovedis DataFrame to Pandas DataFrame Ename Age Country index 0 Michael 29 USA 1 Andy 30 England 2 Tanaka 27 Japan 3 Raul 19 France 4 Yuta 31 Japan
FrovedisServer.shut_down()
続いて、KaggleのCovid-19 vaccineデータを使った操作例を見ていきます。
import pandas as pd
import numpy as np
from datetime import datetime
import time, os
import itertools
import matplotlib.pyplot as plt
from frovedis.exrpc.server import FrovedisServer
from frovedis.dataframe.df import FrovedisDataframe as fd
FrovedisServerを起動します¶
FrovedisServer.initialize("mpirun -np 2 {}".format(os.environ['FROVEDIS_SERVER']))
'[ID: 1] FrovedisServer (Hostname: handson02, Port: 39739) has been initialized with 2 MPI processes.'
Vaccine Data SetをPandasのDataFrameにロードします¶
manufacturers = pd.read_table('../data/country_vaccinations_by_manufacturer.csv', sep=',', engine='python').dropna()
manufacturers.head()
location | date | vaccine | total_vaccinations | |
---|---|---|---|---|
0 | Chile | 2020-12-24 | Pfizer/BioNTech | 420 |
1 | Chile | 2020-12-25 | Pfizer/BioNTech | 5198 |
2 | Chile | 2020-12-26 | Pfizer/BioNTech | 8338 |
3 | Chile | 2020-12-27 | Pfizer/BioNTech | 8649 |
4 | Chile | 2020-12-28 | Pfizer/BioNTech | 8649 |
PandasからFrovedisのDataFrameに変換します。これに伴いdataはベクトルプロセッサのメモリに転送されます。¶
fd_manufacturers = fd(manufacturers)
Frovedis DataFrameに含まれる接種国を抽出後、NumPyへ変換した後にリストへ変換し表示します。¶
location = fd_manufacturers['location']
location = location.to_pandas_dataframe().to_numpy()
x = set(list(itertools.chain.from_iterable(location)))
print(x)
{'Latvia', 'Germany', 'Iceland', 'Czechia', 'Chile', 'Lithuania', 'Romania', 'Italy', 'France', 'United States'}
Frovedis DataFrameの統計データを表示します。¶
fd_manufacturers.describe()
total_vaccinations | |
---|---|
count | 3.491000e+03 |
mean | 4.885988e+06 |
std | 1.635967e+07 |
sum | 1.705698e+10 |
min | 0.000000e+00 |
max | 1.341169e+08 |
Frovedis DataFrameから国別にDataを取り出します。¶
fd_US = fd_manufacturers[fd_manufacturers.location=='United States']
fd_Germany = fd_manufacturers[fd_manufacturers.location=='Germany']
fd_Chile = fd_manufacturers[fd_manufacturers.location=='Chile']
fd_Chile.to_pandas_dataframe().head()
location | date | vaccine | total_vaccinations | |
---|---|---|---|---|
0 | Chile | 2020-12-24 | Pfizer/BioNTech | 420 |
1 | Chile | 2020-12-25 | Pfizer/BioNTech | 5198 |
2 | Chile | 2020-12-26 | Pfizer/BioNTech | 8338 |
3 | Chile | 2020-12-27 | Pfizer/BioNTech | 8649 |
4 | Chile | 2020-12-28 | Pfizer/BioNTech | 8649 |
vaccineの種類ごとに総接種数を計算します。Frovedisのgroupby、aggを使用しvaccine毎に合計を求め表示します。ここではU.S.、Germant、Chileそれぞれの集計結果を表示します。¶
fdUS_out = fd_US.groupby('vaccine').agg({'total_vaccinations': ['sum']})
fdGermany_out = fd_Germany.groupby('vaccine').agg({'total_vaccinations': ['sum']})
fdChile_out = fd_Chile.groupby('vaccine').agg({'total_vaccinations': ['sum']})
fdUS_out.sort("sum_total_vaccinations",ascending=False).to_pandas_dataframe().head()
vaccine | sum_total_vaccinations | |
---|---|---|
0 | Pfizer/BioNTech | 6572931045 |
1 | Moderna | 5789377678 |
2 | Johnson&Johnson | 298233690 |
fdGermany_out.sort("sum_total_vaccinations",ascending=False).to_pandas_dataframe().head()
vaccine | sum_total_vaccinations | |
---|---|---|
0 | Pfizer/BioNTech | 1006759304 |
1 | Oxford/AstraZeneca | 227902088 |
2 | Moderna | 63056380 |
3 | Johnson&Johnson | 68781 |
fdChile_out.sort("sum_total_vaccinations",ascending=False).to_pandas_dataframe().head()
vaccine | sum_total_vaccinations | |
---|---|---|
0 | Sinovac | 656309318 |
1 | Pfizer/BioNTech | 82842894 |
U.S.およびGermanyについてPfizer製vaccine摂取数を抽出します。¶
US_Pfizer = fd_US[fd_US.vaccine=='Pfizer/BioNTech']
US_Pfizer.to_pandas_dataframe().head()
location | date | vaccine | total_vaccinations | |
---|---|---|---|---|
0 | United States | 2021-01-12 | Pfizer/BioNTech | 5488697 |
1 | United States | 2021-01-13 | Pfizer/BioNTech | 6025872 |
2 | United States | 2021-01-15 | Pfizer/BioNTech | 7153268 |
3 | United States | 2021-01-19 | Pfizer/BioNTech | 8874811 |
4 | United States | 2021-01-20 | Pfizer/BioNTech | 9281063 |
Germany_Pfizer = fd_Germany[fd_Germany.vaccine=='Pfizer/BioNTech']
Germany_Pfizer.to_pandas_dataframe().head()
location | date | vaccine | total_vaccinations | |
---|---|---|---|---|
0 | Germany | 2020-12-27 | Pfizer/BioNTech | 24473 |
1 | Germany | 2020-12-28 | Pfizer/BioNTech | 42813 |
2 | Germany | 2020-12-29 | Pfizer/BioNTech | 92363 |
3 | Germany | 2020-12-30 | Pfizer/BioNTech | 154903 |
4 | Germany | 2020-12-31 | Pfizer/BioNTech | 204951 |
U.S., GermanyでのPfizer製vaccine接種時系列データをPandasのDataFrameに変換した後にグラフ化します。¶
US_data = US_Pfizer.to_pandas_dataframe()
Germany_data = Germany_Pfizer.to_pandas_dataframe()
fig = plt.figure(figsize=(16,8))
ax1 = fig.add_subplot(2,2,1)
ax2 = fig.add_subplot(2,2,2)
x1 = range(0,len(US_data['date']),25)
ax1.plot(US_data['date'], US_data['total_vaccinations'])
ax1.set_xticks(x1)
ax1.set_title('United States: Pfizer', size=15)
ax1.set_xlabel('Date')
ax1.set_ylabel('Total vaccinations x100000000')
ax2.plot(Germany_data['date'], Germany_data['total_vaccinations'])
x2 = range(0,len(Germany_data['date']),25)
ax2.plot(Germany_data['date'], Germany_data['total_vaccinations'])
ax2.set_xticks(x2)
ax2.set_title('Germany: Pfizer', size=15)
ax2.set_xlabel('Date')
ax2.set_ylabel('Total vaccinations x100000000')
plt.show()
今回はFrovedisのDataFrameを使用したデータ処理について御紹介しました。
関連リンク
AL/ML開発向けオープンソースプラットフォーム「Frovedis」
SX-Aurora TSUBASAテクニカルセミナー特設サイト
本コラム内容を踏まえたテクニカルセミナー動画公開中。第1回講演3参照。
最新資料/カタログはこちらからダウンロード
ご紹介資料、各種カタログをダウンロードいただけます。
My NEC登録が必要です
My NEC登録が必要です
