Python で解析 11
“Advent Calendar 2013 - Python で解析!” の十一日目。DataFrame - 7
1. 前回の補足
今回は concat を取り上げるのだが、その前に、十日目の記事を読み返していたら、書き忘れていたことがあったので、先に補足しておく。
In [10]: df4 = df1.join([df2, df3]) In [11]: df4 Out[11]: 体重 名前 性別 身長 誕生日 好きなもの 3B005 79 山田 男 181 1982/02/02 ばなな 3B003 71 鈴木 男 173 1983/03/03 いちご 3B002 51 佐藤 女 159 1984/04/04 NaN 3B001 52 木村 女 164 NaN メロン
上の join の場合、'how' に 'left' を指定したのと同じになる。
In [12]: df1.join([df2, df3], how='left') Out[12]: 体重 名前 性別 身長 誕生日 好きなもの 3B005 79 山田 男 181 1982/02/02 ばなな 3B003 71 鈴木 男 173 1983/03/03 いちご 3B002 51 佐藤 女 159 1984/04/04 NaN 3B001 52 木村 女 164 NaN メロン
merge の場合の省略値は 'inner' だったが、join でも 'inner' を指定することができる。
In [13]: df1.join([df2, df3], how='inner') Out[13]: 体重 名前 性別 身長 誕生日 好きなもの 3B005 79 山田 男 181 1982/02/02 ばなな 3B003 71 鈴木 男 173 1983/03/03 いちご
'outer' も指定できる。
In [14]: df1.join([df2, df3], how='outer') Out[14]: 体重 名前 性別 身長 誕生日 好きなもの 3B001 52 木村 女 164 NaN メロン 3B002 51 佐藤 女 159 1984/04/04 NaN 3B003 71 鈴木 男 173 1983/03/03 いちご 3B004 NaN NaN NaN NaN 1981/01/01 りんご 3B005 79 山田 男 181 1982/02/02 ばなな
だが、 join で複数の DataFrame をつなぐ時には 'right' は指定できない。
In [15]: df1.join([df2, df3], how='right') (中略) ValueError: Only can inner (intersect) or outer (union) join the other axis
一つだけなら OK。
In [16]: df1.join(df2, how='right') Out[16]: 体重 名前 性別 身長 誕生日 3B004 NaN NaN NaN NaN 1981/01/01 3B005 79 山田 男 181 1982/02/02 3B003 71 鈴木 男 173 1983/03/03 3B002 51 佐藤 女 159 1984/04/04
2. では、 concat のための準備を
In [1]: import pandas as pd In [2]: df1 = pd.DataFrame({ ...: u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'], ...: u'性別': [u'男', u'男', u'女', u'女'] , ...: u'身長': [181, 173, 159, 164], ...: u'体重': [79, 71, 51, 52] ...: }, ...: index=['3B005', '3B003', '3B002', '3B001'] ...: ) In [3]: df2 = pd.DataFrame({ ...: u'名前': [u'田中', u'山田', u'鈴木', u'佐藤'], ...: u'誕生日': ['1981/01/01', '1982/02/02', '1983/03/03', '1984/04/04'] ...: }, ...: index=['3B004','3B005','3B003', '3B002'] ...: ) In [4]: df1 Out[4]: 体重 名前 性別 身長 3B005 79 山田 男 181 3B003 71 鈴木 男 173 3B002 51 佐藤 女 159 3B001 52 木村 女 164 In [5]: df2 Out[5]: 名前 誕生日 3B004 田中 1981/01/01 3B005 山田 1982/02/02 3B003 鈴木 1983/03/03 3B002 佐藤 1984/04/04
3. で、 concat を
merge や join は横につなぐイメージ (結合) だが、 concat は縦につなぐイメージ (連結)。通常の python の list + list のようなものだ。
In [6]: df3 = pd.concat([df1, df2]) In [7]: df3 Out[7]: 体重 名前 性別 誕生日 身長 3B005 79 山田 男 NaN 181 3B003 71 鈴木 男 NaN 173 3B002 51 佐藤 女 NaN 159 3B001 52 木村 女 NaN 164 3B004 NaN 田中 NaN 1981/01/01 NaN 3B005 NaN 山田 NaN 1982/02/02 NaN 3B003 NaN 鈴木 NaN 1983/03/03 NaN 3B002 NaN 佐藤 NaN 1984/04/04 NaN
レコードは単純に追加されるので、index が同じでも関係がなく、別のレコードして追加される。同じ名前のカラムは統合され、そうでないものは追加される。
In [8]: df3.columns Out[8]: Index([u'体重', u'名前', u'性別', u'誕生日', u'身長'], dtype=object) In [9]: df3.index Out[9]: Index([u'3B005', u'3B003', u'3B002', u'3B001', u'3B004', u'3B005', u'3B003', u'3B002'], dtype=object)
連結後は index が一意になってないことに注意。DataFrame の index は RDBMS のようにユニーク制約という訳ではないようだ。その代わりに (?)、ユニークかどうかをチェックすることができる。
In [10]: df3.index.is_unique Out[10]: False
今回はこんなところで。
Python で解析 10
“Advent Calendar 2013 - Python で解析!” の十日目。DataFrame - 6
1. お決まりの準備を…
今回は DataFrame の join について。 join は merge のお手軽版といったところのようだ。インデックスがあって、カラムが重複していない場合には、merge よりもお手軽なので、使いやすいと思われる。という訳で、準備を。
In [1]: import pandas as pd In [2]: df1 = pd.DataFrame({ ...: u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'], ...: u'性別': [u'男', u'男', u'女', u'女'] , ...: u'身長': [181, 173, 159, 164], ...: u'体重': [79, 71, 51, 52] ...: }, ...: index=['3B005', '3B003', '3B002', '3B001'] ...: ) In [3]: df2 = pd.DataFrame({ ...: u'誕生日': ['1981/01/01', '1982/02/02', '1983/03/03', '1984/04/04'] ...: }, ...: index=['3B004','3B005','3B003', '3B002'] ...: ) In [4]: df3 = pd.DataFrame({ ...: u'好きなもの': [u'りんご', u'ばなな', u'いちご', u'メロン'], ...: }, ...: index=['3B004','3B005','3B003', '3B001'] ...: ) In [5]: df1 Out[5]: 体重 名前 性別 身長 3B005 79 山田 男 181 3B003 71 鈴木 男 173 3B002 51 佐藤 女 159 3B001 52 木村 女 164 In [6]: df2 Out[6]: 誕生日 3B004 1981/01/01 3B005 1982/02/02 3B003 1983/03/03 3B002 1984/04/04 In [7]: df3 Out[7]: 好きなもの 3B004 りんご 3B005 ばなな 3B003 いちご 3B001 メロン
今回は DataFrame が三つある。そして、それぞれのカラムが別々で、名前や性別は df1 にしかない。その代わりに index が付けてある。 index は初めて登場するが、RDBMS でいうところのプライマリーキーのようなものだ。そして、プリフィックスとして '3B' が付いているのは "三年 B 組、金八先生!" を思い出して付けてみただけ。深い意味はない。
2. 早速 join
論より証拠ということで join してみる。
In [8]: df1.join(df2) Out[8]: 体重 名前 性別 身長 誕生日 3B005 79 山田 男 181 1982/02/02 3B003 71 鈴木 男 173 1983/03/03 3B002 51 佐藤 女 159 1984/04/04 3B001 52 木村 女 164 NaN
逆にするとこうなる。
In [9]: df2.join(df1) Out[9]: 誕生日 体重 名前 性別 身長 3B004 1981/01/01 NaN NaN NaN NaN 3B005 1982/02/02 79 山田 男 181 3B003 1983/03/03 71 鈴木 男 173 3B002 1984/04/04 51 佐藤 女 159
3. 複数の join
たぶん、 join の真骨頂はこれ。
In [10]: df4 = df1.join([df2, df3]) In [11]: df4 Out[11]: 体重 名前 性別 身長 誕生日 好きなもの 3B005 79 山田 男 181 1982/02/02 ばなな 3B003 71 鈴木 男 173 1983/03/03 いちご 3B002 51 佐藤 女 159 1984/04/04 NaN 3B001 52 木村 女 164 NaN メロン
インデックスさえ一致していれば (& 重複カラムがなければ)、複数の DataFrame を簡単に統合できてしまう。これに慣れてしまうと、SQL が面倒になってしまうのが弊害か…。
4. おまけ
カラムやインデックスを確認する方法は次の通り。
In [12]: df4.columns Out[12]: Index([u'体重', u'名前', u'性別', u'身長', u'誕生日', u'好きなもの'], dtype=object) In [13]: df4.index Out[13]: Index([u'3B005', u'3B003', u'3B002', u'3B001'], dtype=object)
付け替えることもできる。
In [14]: df4.columns = ['weight', 'name', 'sex', 'height', 'birthday', 'favorite food'] In [15]: df4.columns Out[15]: Index([u'weight', u'name', u'sex', u'height', u'birthday', u'favorite food'], dtype=object)
以後、新しいカラム名を使って操作することになる。
In [16]: df4[u'weight'] Out[16]: 3B005 79 3B003 71 3B002 51 3B001 52 Name: weight, dtype: int64
今回はこんなところで。
Python で解析 9
“Advent Calendar 2013 - Python で解析!” の九日目。DataFrame - 6
1. お決まりの準備を…
今回は DataFrame のマージについて。マージとは、二つのデータフレームを結合することで、SQL で言うところの join と同等のもので、数学的には集合演算とかベン図とか…を思い出してもらえればいいだろう。さて、その前にいつものように準備を。
In [1]: import pandas as pd In [2]: df1 = pd.DataFrame({ ...: u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'], ...: u'性別': [u'男', u'男', u'女', u'女'] , ...: u'身長': [181, 173, 159, 164], ...: u'体重': [79, 71, 51, 52] ...: }) In [3]: df2 = pd.DataFrame({ ...: u'名前': [u'田中', u'山田', u'鈴木', u'佐藤'], ...: u'性別': [u'男', u'女', u'男', u'女'] , ...: u'誕生日': ['1981/01/01', '1982/02/02', '1983/03/03', '1984/04/04'] ...: }) In [4]: df1 Out[4]: 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173 2 51 佐藤 女 159 3 52 木村 女 164 In [5]: df2 Out[5]: 名前 性別 誕生日 0 田中 男 1981/01/01 1 山田 女 1982/02/02 2 鈴木 男 1983/03/03 3 佐藤 女 1984/04/04
今回はマージを取り扱うので、データは二つ用意する。誕生日のデータの方には、田中くんが増えていて、山田さんが女性になっていて、木村さんがいないという違いがある。そして、データの順番が一致していない。マージの振る舞いを確認するために、わざと少しばかりややこしくしている。
1. 何も考えずにマージ
In [6]: pd.merge(df1, df2) Out[6]: 体重 名前 性別 身長 誕生日 0 71 鈴木 男 173 1983/03/03 1 51 佐藤 女 159 1984/04/04
件数が少なくなってしまったが、表示されている各数値に間違いはないので、どうやらマージはできたようだ。
2. キーカラムを指定してマージ
Pandas の merge は、指定したそれぞれの DataFrame の同じカラム名をキーにしてマージする。なので、実は次のようにカラム名を指定したのと同じことなのだ。
In [7]: pd.merge(df1, df2, on=[u'名前', u'性別']) Out[7]: 体重 名前 性別 身長 誕生日 0 71 鈴木 男 173 1983/03/03 1 51 佐藤 女 159 1984/04/04
SQL もこのぐらい便宜を計らってほしいものだが…というのはさておき…。
試しに性別がキーに含まれないようにして、名前だけでマージすると次のようになる。
In [8]: pd.merge(df1, df2, on=u'名前') Out[8]: 体重 名前 性別_x 身長 性別_y 誕生日 0 79 山田 男 181 女 1982/02/02 1 71 鈴木 男 173 男 1983/03/03 2 51 佐藤 女 159 女 1984/04/04
性別が一致しなくても、名前だけで一致すればいいので、山田氏のレコードが増えた。その一方で、性別項目が二つできている。性別のサフィックスの '_x' が左に書いた df1 のもので、'_y' が右に書いた df2 のもの。
3. レコード数の差異を制御
df1 と df2 が完全に一致してないので、それをどう取り扱うかを制御してみる。SQL で言うところの left join とか outer join とか…のことだ。
最初の例では 2 件になってしまったが、それは両方に存在するレコードのみが抽出されたからで、以下と同等。
In [9]: pd.merge(df1, df2, how='inner') Out[9]: 体重 名前 性別 身長 誕生日 0 71 鈴木 男 173 1983/03/03 1 51 佐藤 女 159 1984/04/04
左側 (すなわち df1) さえあれば、右側 (すなわち df2) がなくてもかまわないなら、次のように書く。
In [10]: pd.merge(df1, df2, how='left') Out[10]: 体重 名前 性別 身長 誕生日 0 79 山田 男 181 NaN 1 71 鈴木 男 173 1983/03/03 2 51 佐藤 女 159 1984/04/04 3 52 木村 女 164 NaN
逆に左側がなくても、右側さえあれば良いなら、次のように書く。
In [11]: pd.merge(df1, df2, how='right') Out[11]: 体重 名前 性別 身長 誕生日 0 71 鈴木 男 173 1983/03/03 1 51 佐藤 女 159 1984/04/04 2 NaN 田中 男 NaN 1981/01/01 3 NaN 山田 女 NaN 1982/02/02
どちらか片方にさえあれば有効とするなら、how に 'outer' を指定する。
In [12]: pd.merge(df1, df2, how='outer') Out[12]: 体重 名前 性別 身長 誕生日 0 79 山田 男 181 NaN 1 71 鈴木 男 173 1983/03/03 2 51 佐藤 女 159 1984/04/04 3 52 木村 女 164 NaN 4 NaN 田中 男 NaN 1981/01/01 5 NaN 山田 女 NaN 1982/02/02
これが最大件数になる。
いずれの例でも同じく、データが存在しないところは NaN (Not a Number) となる。
なお、ここまでの例で 'pd.mege()' としているが、'df1.merge(df2)' のように書くことともできる。今回の説明の on や how の意味も同じように使える。'df1.merge(df2)' の方がオブジェクト指向らしい書き方なのだが、軽く調べた限りではマイノリティーな感じ。データマイニングする人は、オブジェクト指向にこだわらない傾向があるのかもしれない。
今回はこんなところで。
Python で解析 8
“Advent Calendar 2013 - Python で解析!” の八日目。DataFrame - 5
1. お決まりの準備を…
今回は DataFrame の保存だが、その前に例によって準備を。
In [1]: import pandas as pd In [2]: df = pd.DataFrame({ ...: u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'], ...: u'性別': [u'男', u'男', u'女', u'女'] , ...: u'身長': [181, 173, 159, 164], ...: u'体重': [79, 71, 51, 52] ...: }) In [3]: df Out[3]: 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173 2 51 佐藤 女 159 3 52 木村 女 164
2. バイナリ形式のセーブ
DataFrame はそのまま保存できる。
df.save('hoge.pickle')
…が、save すると "save is deprecated, use to_pickle" と警告が表示されるので、to_pickle の方を使うようにする。
df.to_pickle('hoge.pickle')
保存したファイルを読み込む場合は read_pickle を使う。
In [5]: df2 = pd.read_pickle('hoge.pickle') In [6]: df2 Out[6]: 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173 2 51 佐藤 女 159 3 52 木村 女 164
再現できた。
3. テキスト形式のセーブ
to_csv でテキスト形式で保存できる。
df.to_csv('hoge.csv')
日本語を含む場合は、encoding を指定する。
In [9]: df.to_csv('hoge.csv', encoding='utf-8') In [10]: !cat hoge.csv ,体重,名前,性別,身長 0,79,山田,男,181 1,71,鈴木,男,173 2,51,佐藤,女,159 3,52,木村,女,164
タブ区切りなら、sep を指定する。
In [11]: df.to_csv('hoge.tsv', encoding='utf-8', sep='\t') In [12]: In [10]: !cat hoge.tsv 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173 2 51 佐藤 女 159 3 52 木村 女 164
4. Excel 形式ののセーブ
Excel 形式でも保存できるが、そのためには xlwt をインストールしておく必要がある。
$ pip install xlwt
テキスト形式の保存より、少し手間がかかるが、次のような手順で Excel 形式で保存できる。
In [13]: xl = pd.ExcelWriter('hoge.xls') In [14]: df.to_excel(xl, 'Sheet1') In [15]: xl.save() In [16]: !ls -l hoge.xls -rw-r--r-- 1 tokutomi staff 5632 12 8 09:27 hoge.xls
pythonista ならこう書きたいところだが…。
with(pd.ExcelWriter('hoge.xls')) as xl: df.to_excel(xl, 'Sheet1')
"AttributeError: __exit__" とのことで、with には対応してないようだ。残念…。
そういえば、さらっと '!cat' や '!ls' のようにシェルコマンドを書いているが、 ipython から抜けずにシェルコマンドを使えて便利である。実は先頭の '!' を付けずに 'ls' とだけしても使えるのだが、同じ変数名があったりなどすると、そちらが優先されるので、 '!' を付けて実行する方が確実だろう。
今回は、こんなところで。
Python で解析 7
“Advent Calendar 2013 - Python で解析!” の七日目。matplotlib - 2
1. 準備
Notebook を使いたいところだが、ブログにコードを書くのにスクリーンショットでは都合が悪いので、ターミナルの ipython を使う。起動時に '--pylab=inline' を付けておくと、'show()' を実行しなくてもチャートが表示されて便利。
$ ipython --pylab=inline
今回は pylab もインポートしておく。
In [1]: import pandas as pd In [2]: import pylab as pl In [3]: import pandas as pd In [4]: df = pd.DataFrame({ ...: u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'], ...: u'性別': [u'男', u'男', u'女', u'女'] , ...: u'身長': [181, 173, 159, 164], ...: u'体重': [79, 71, 51, 52] ...: }) In [5]: df Out[5]: 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173 2 51 佐藤 女 159 3 52 木村 女 164
2. 散布図
データを手に入れたら 'とりあえず散布図' ということで。
In [6]: pl.scatter(df[u'身長'], df[u'体重']) Out[6]: <matplotlib.collections.PathCollection at 0x1077a2e90>
この散布図は Pandas でなくても matplotlib に配列を渡して表示できる。
なお、ipython の起動時に pylab を読み込んでいるので、'pl.scatter()' ではなく 'scatter()' として使うこともできるのだが、後々のことを考えて、どのモジュールの機能を使うのかが明らかである 'pl.scatter()' という書き方を選んでいる。
3. 散布図マトリックス
Pandas だとこれが便利。
In [7]: pd.scatter_matrix(df) Out[7]: array([[<matplotlib.axes.AxesSubplot object at 0x1077b9f50>, <matplotlib.axes.AxesSubplot object at 0x1078d28d0>], [<matplotlib.axes.AxesSubplot object at 0x1078f64d0>, <matplotlib.axes.AxesSubplot object at 0x1077c9310>]], dtype=object)
Python で解析 6
“Advent Calendar 2013 - Python で解析!” の六日目。Pandas で DataFrame - 4
1. お決まりの準備を…
In [1]: import pandas as pd In [2]: df = pd.DataFrame({ ...: u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'], ...: u'性別': [u'男', u'男', u'女', u'女'] , ...: u'身長': [181, 173, 159, 164], ...: u'体重': [79, 71, 51, 52] ...: }) In [3]: df Out[3]: 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173 2 51 佐藤 女 159 3 52 木村 女 164
2. Series と DataFrame
ここまで便利に DataFrame を使ってきたが、念のために確認しておく。
In [4]: type(df) Out[4]: pandas.core.frame.DataFrame
DataFrame の列も確認してみる。
In [5]: type(df[u'名前']) Out[5]: pandas.core.series.Series
Series が返って来るようだ。DataFrame も Series も Pandas で定義されていて、 Series は一次元のデータを取り扱う。
In [6]: type(df.iloc[1]) Out[6]: pandas.core.series.Series
行を取り出しても Series になっている。
これまで DataFrame の関数を呼び出していたが、実は Series にも使える。
In [7]: df[u'体重'].sum() Out[7]: 253 In [8]: df[u'体重'].describe() Out[8]: count 4.000000 mean 63.250000 std 13.961256 min 51.000000 25% 51.750000 50% 61.500000 75% 73.000000 max 79.000000 dtype: float64
どうやら、 DataFrame の同等の関数は、各 Series の関数を呼び出して、その結果を表示していたようだ。
3. 条件に合致した行を選択…の補足
前回、条件に合致した行の選択方法を書いた。
In [9]: df.loc[df[u'身長']>170] Out[9]: 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173
試しに、この条件文だけを実行してみる。
In [10]: df[u'身長']>170 Out[10]: 0 True 1 True 2 False 3 False Name: 身長, dtype: bool In [11]: type(df[u'身長']>170) Out[11]: pandas.core.series.Series
bool の Series が戻ってくる。どうやら条件を渡して行を選択しているというよりも、 bool の配列を使ってマスクして行を抽出しているようだ。試しに、条件文の代わりに bool の配列を渡してみると、こうなる。
In [12]: df.loc[[True, True, False, False]] Out[12]: 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173
ただし、この配列は行数に一致していなければならない。試してみると、エラーが表示される。
In [13]: df.loc[[True, True, False, False, True]] Out[13]: # (中略) KeyError: Exception('Indices must be nonzero and less than the axis length',)
今回は、こんなところで。
Python で解析 5
“Advent Calendar 2013 - Python で解析!” の五日目。Pandas で DataFrame - 3
1. 例のごとく準備を…。
In [1]: import pandas as pd In [2]: df = pd.DataFrame({ ...: u'名前': [u'山田', u'鈴木', u'佐藤', u'木村'], ...: u'性別': [u'男', u'男', u'女', u'女'] , ...: u'身長': [181, 173, 159, 164], ...: u'体重': [79, 71, 51, 52] ...: }) In [3]: df Out[3]: 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173 2 51 佐藤 女 159 3 52 木村 女 164
2. 任意の行を選択
まずは、特定の行を取り出す。R は 1 から始まるが、Pandas では 0 から始まるという微妙な差がある。
In [4]: df.iloc[2] Out[4]: 体重 51 名前 佐藤 性別 女 身長 159 Name: 2, dtype: object
配列を渡して、任意の複数行を取り出すこともできる。
In [5]: df.iloc[[3,1]] Out[5]: 体重 名前 性別 身長 3 52 木村 女 164 1 71 鈴木 男 173
範囲指定で取り出すことも可能。R では "以上:以下" で指定するが、 Pandas では "以上:未満" で指定する。
In [6]: df.iloc[1:3] Out[6]: 体重 名前 性別 身長 1 71 鈴木 男 173 2 51 佐藤 女 159
3. 条件に合致した行を選択
In [7]: df.loc[df[u'身長']>170] Out[7]: 体重 名前 性別 身長 0 79 山田 男 181 1 71 鈴木 男 173
In [8]: df.loc[df[u'性別']==u'女'] Out[8]: 体重 名前 性別 身長 2 51 佐藤 女 159 3 52 木村 女 164
4. 条件に合致した行の特定の列を選択
In [9]: df.loc[df[u'性別']==u'女', u'体重'] Out[9]: 2 51 3 52 Name: 体重, dtype: int64
In [10]: df.loc[df[u'性別']==u'女', [u'身長',u'体重']] Out[10]: 身長 体重 2 159 51 3 164 52
5. そして、要約統計量
行列を選択した結果は DataFrame が返ってくる。なので、そのまま DataFrame の関数が使える。
In [11]: df.loc[df[u'性別']==u'女', [u'身長',u'体重']].describe() Out[11]: 身長 体重 count 2.000000 2.000000 mean 161.500000 51.500000 std 3.535534 0.707107 min 159.000000 51.000000 25% 160.250000 51.250000 50% 161.500000 51.500000 75% 162.750000 51.750000 max 164.000000 52.000000
今回はこんなところで。