2021年6月18日金曜日

ちょっと惹かれるPython1行コード(その2)

 【what is this】前回に引き続き、短くて美しい1行コードを検討します。参考文献[1]を参考にしています。Pythonの初心者が中級へステップアップするのに適しています。小生もこれに該当しますので、個人的な忘備録でもあります。

例題:漁獲高の平均を上回る漁港をリストアップする
 今回データ分析の対象とするデータ(参考文献[2]を参考とした)を以下に示します。Python numpy配列であるFHには、主要な漁港名9つを格納しています。そして、別のnumpy配列Vには、この漁港の順に、2014年〜2018年の5年間の漁獲高(水揚げ量)を万トン単位で格納してあります。

【解くべき問題】
 上記データ45件(=9漁港x5年)の平均値を一回でも超えた漁港を示すこと。
【解答プログラム】
 以下の1行コードが解答プログラム(出力込み)です!
答えは、"銚子"、"釧路"、"焼津"の3漁港でした。

一行コードの分解 ...
 上記1行コードをすぐに理解できる人は少ないかもしれません。そこで、その中身を分解してみます。最後には、「なるほど、素晴らしい!」となるでしょう。

(1)平均値を求める
 これは下図のように、簡単です。

(2)平均値を超えるか否かを真偽配列で表す
 この真偽の配列は、下図のように生成することができます。numpyのbroadcastが働いています。

(3)"True"の位置のインデックスを求める
 上図の真偽配列において、'True'となる位置のインデックスを下図のように求めます。ここで、numpy関数nonzeroが使われていますが、'nonzero'は、Pythonでは、'True'に対応することに注意します。全45件のうち、13件が'nonzero'であり、その位置のインデックスは、下図のように2次元配列で表されます。
 例えば、上段の'0'と下段の'0'のペアは、銚子漁港の最初(2014年)のデータが、平均直を超えていることを意味します。また、釧路漁港(上段インデックス4)は、3回平均値を超えたことが分かります。

(4)漁獲高の絶対値はここでは不要
 上図は、2次元配列になっていますが、ここでは、漁港名に対するインデックスだけわかれば良いので、最初の1次元配列だけを取り出します。下図で、'[0]'がそれを実現します。

(5)インデックスのリストを配列に与える
 次に、このインデックスを漁港名に変換するのですが、以下のように、インデックスのリストを配列FHに与えることができます。

 
 これに従って処理を続けると、以下のように、漁港名のリストが得られます。

(6)最後は集合(set)で仕上げ
  最後に、漁港名の重複を除去するため、set関数を適用します。完成!

補足(Excelファイルを使う)
 上記のnumpy配列FHとVの設定に、以下のようなエクセルファイル(fishVol.xlsx)を利用しても良いでしょう。(pandasを使いますが、別途openpyxl, xlrdのインストールを要します。)

[参考文献]
[1] Christian Mayer, "Python One-Liners", No Starch  Press, 2020.
[2] 図録 主要漁港別水揚げ高(日本地図)とその推移, 2020.https://honkawa2.sakura.ne.jp/7400.html

0 件のコメント:

コメントを投稿