ゆとり世代の自由研究

勉強が一生終わりません

Flaskの基本

Flask

 pythonでwebアプリをつくるためにFlaskを調査しました。

仮想環境の構築

 最初に作成したいフォルダに仮想環境を構築します。

$ python -m venv venv

 起動方法

$ venv\Scripts\activat

 終了方法

$ deactivate

Flaskのインストール

$ pip install Flask

その他のライブラリインストール

 エラーが発生したので追加しました。

$ pip install arrow
$ pip install ipython
$ pip install ipywidgets
$ pip install psutil 
$ pip install pyarrow

Hello World アプリケーション

 ファイル名はhello.py。flask.pyはエラーになるので使用禁止。

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"
  1. 最初にFlaskクラスをimport。このクラスのインスタンスWSGI(Web Server Gateway Interface)アプリケーションです。
  2. 次に、Flaskクラスのインスタンスを作成します。最初の引数はアプリケーションのモジュールまたはパッケージの名前で、nameがショートカットとして機能します。これはテンプレート、静的ファイルなどのリソースを探す場所をFlaskが知るために必要になります。
  3. それからroute()デコレータを使って、どのURLが関数のトリガーかをFlaskに伝えます。
  4. その関数はユーザのブラウザで表示したいメッセージを返します。標準のコンテント・タイプはHTMLです。

Flaskの起動

 公式docsにはflaskコマンドが記載してありますが、環境変数の設定が不明だったのでpythonコマンドで起動。hello.pyを起動します。

$ python -m flask --app hello run

 デバッグモードだと、サーバー起動しながら編集できます。
 ブラウザの更新ボタンで反映されます。

$ python -m flask --app hello --debug run

ブラウザ表示

 http://127.0.0.1:5000/でブラウザ表示されます。
 サーバー停止はcrtl+cです。

競技プログラミングにpythonで挑む

Atcoderに挑戦

プログラミングの技術向上のためにAtCoderに挑戦してみましたが、
pythonではTLE(時間超過)してしまうので対策を調査しました。

atcoder.jp

標準入力について

 pythonの標準入力input()は遅いようです。

普通のやり方

n = int(input())
a = [int(input()) for _ in range(n)]

早いやり方

import sys
input = sys.stdin.readline
n = int(input())
a = [int(input()) for _ in range(n)]

Listについて

 Listへのランダムアクセスは遅いようです。
 appendpopは早いがinsertや末尾以外のpopは遅い。
 先頭へ追加・削除をしたい場合はdequeを使う。
 inmaxminは遅いのでsetDictを使う。

普通のやり方

Operation Code Average Case
Append l.append(x) O(1)
Pop last l.pop() O(1)
Pop intermediate l.pop(i) O(n)
Insert l.insert(i, x) O(n)
in x in l O(n)
min, max min(l), max(l) O(n)

早いやり方

data structure Operation Code Average Case
set in x in s O(1)
set add s.add(x) O(1)
dict in x in d O(1)
dict Get item d[x] O(1)
dict Set item d[x] = y O(1)

Pythonのpandasライブラリ

pandasとは

 DataFrameと呼ばれる表形式のデータを取り扱うライブラリです。

読み書き方法

 読み取りは.read_*メソッド、書き込みはto_*メソッドを使います。
 *には、csvjsonxml、html、excelなどが使えます。データベースとの連携はsqlです。

titanic = pd.read_csv("data/titanic.csv")

抽出方法

 データの抽出は、[ ]で行います。

ages = titanic["Age"]

 ブールインデックスという方法もあります。

above_35 = titanic[titanic["Age"] > 35]

 loc、ilocメソッドを使った方法もあります。

adult_names = titanic.loc[titanic["Age"] > 35, "Name"]
titanic.iloc[9:25, 2:5]

列の追加

 演算式を用いて列を作成して追加できます。

air_quality["london_mg_per_cubic"] = air_quality["station_london"] * 1.882
air_quality["ratio_paris_antwerp"] = (
                        air_quality["station_paris"] / air_quality["station_antwerp"]

集計関数

 基本的な統計量(平均値、中央値、最小値、最大値、カウント数...)が計算できます。

titanic["Age"].mean()
titanic[["Age", "Fare"]].median()
titanic[["Age", "Fare"]].describe()
titanic.agg(
    {
        "Age": ["min", "max", "median", "skew"],
        "Fare": ["min", "max", "median", "mean"],
    }
)

 groupbyを用いて層別集計できます。

titanic[["Sex", "Age"]].groupby("Sex").mean()

indexの変更

df.index
df.reset_index
inplace,drop引数

columnsの変更

df.set_columns
df. columns

結合

 concatメソッドで縦横に結合できます。axis=0で縦、axis=1で横結合です。

air_quality = pd.concat([air_quality_pm25, air_quality_no2], axis=0)

 mergeメソッドで列をキーとして結合できます。

air_quality = pd.merge(air_quality, stations_coord, how="left", on="location")

再成形

 pivotmeltメソッドが使えます。

no2_subset.pivot(columns="location", values="value")

air_quality.pivot_table(
    values="value", index="location", columns="parameter", aggfunc="mean"
)
no_2 = no2_pivoted.melt(id_vars="date.utc")

no_2 = no2_pivoted.melt(
    id_vars="date.utc",
    value_vars=["BETR801", "FR04014", "London Westminster"],
    value_name="NO_2",
    var_name="id_location",
)

map ラムダ式

 df.map.ラムダ式の記法が使えます。

グラフ描画

 matplotlibライブラリを用いてグラフ化できます。

import matplotlib.pyplot as plt
air_quality = pd.read_csv("data/air_quality_no2.csv", index_col=0, parse_dates=True)
air_quality.plot()
plt.show()

時系列処理

 時間はdatetime型で取り扱いができます。

air_quality["datetime"] = pd.to_datetime(air_quality["datetime"])

pd.read_csv("../data/air_quality_no2_long.csv", parse_dates=["datetime"])

文字列処理

 文字型はstr型と同じ取り扱いができます。

titanic["Name"].str.lower()
titanic["Name"].str.split(",")
titanic["Surname"] = titanic["Name"].str.split(",").str.get(0)
titanic["Name"].str.contains("Countess")
titanic[titanic["Name"].str.contains("Countess")]
titanic["Name"].str.len()
titanic["Name"].str.len().idxmax()
titanic.loc[titanic["Name"].str.len().idxmax(), "Name"]
titanic["Sex_short"] = titanic["Sex"].replace({"male": "M", "female": "F"})

pythonでJSONを扱う方法

目的

 webAPIで取得したJSON形式データをpythonで取り扱いたいと思います。
JSONとは、{}などを用いた記法であり、そのままでは文字列型であることから、 dict型などpythonオブジェクトに変換して取り扱う必要があります。
https://docs.python.org/ja/3/library/json.html

JSONライブラリ

 最初にimportします。

import json

エンコード方法(pythonオブジェクトをJSON形式に変換)

 pythonオブジェクトをJSON形式に変換するするために.dumpsメソッドを使用します。
 変換されたJSON形式のデータ型はstr型です。
 よく似た名前のメソッドにdumpがありますが、これはデータをJSON形式にエンコードしてファイル保存するメソッドですので、間違えないようします。
dumpssstr型のsかどうかはわかりませんが、s付きはstr変換、sなしはファイル変換と覚えるようにしています。

js = json.dumps([1, 2, 3, {'4': 5, '6': 7}], separators=(',', ':'))
'[1,2,3,{"4":5,"6":7}]'
print(type(js))
print(js)

結果

<class 'str'>
[1,2,3,{"4":5,"6":7}]

デコード方法(JSON形式からpythonオブジェクトに変換)

 JSONデータ形式に変換するために.loadsメソッドを使用します。
 例えば、変換されたリスト形式のデータ型はlist型です。
.dumpsと同様に.loadsloadがありますので、注意します。

js = json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
print(type(js))
print(js)

結果

<class 'list'>
['foo', {'bar': ['baz', None, 1.0, 2]}]

変換表(エンコード)

PYTHON JSON
dict object
list, tuple array
str string
int、float と int や float の派生列挙型 number
True true
False false
None null

dumpとdumps(書き込み)

dump: objJSON 形式に変換してfp (ファイルオブジェクト) へ流し込みます。

json.dump(obj, fp, *)

dumps: objJSON 形式の str オブジェクトに変換します。

json.dumps(obj, *)

loadとloads(読み取り)

load: JSON形式のfp (ファイルオブジェクト) を読み取り、pythonオブジェクトに変換します。

json.load(fp, *)

loads: JSON形式のstrインスタンスpythonオブジェクトに変換します。

json.loads(s, *)

結論

 JSON形式のデータファイルを.loadメソッドでpythonオブジェクトに変換する。
 データインスタンスであれば、loadsメソッドでpythonオブジェクトに変換する。
 ⇒dict型、list型としてpythonで取り扱います。

streamlit

st.write

アプリに引数を書き込みます。

 

st.write(*args, unsafe_allow_html=False, **kwargs)

数値、データ フレーム、スタイル付きデータ フレーム、各種オブジェクトなどの他のデータ形式も受け入れます。チャート オブジェクトも受け入れます。

 

Streamlit が独自の行に変数またはリテラル値を見つけると、それを を使用してアプリに自動的に書き込みます。

また、マジックは docstring を無視できるほど賢いです。つまり、ファイルと関数の先頭にある文字列は無視されます。

Streamlit コマンドをより明示的に呼び出したい場合は、~/.streamlit/config.toml次の設定でいつでもマジックをオフにすることができます。

[runner]

magicEnabled = false

 

Markdown としてフォーマットされた文字列を表示します。

st.markdown(body, unsafe_allow_html=False, *, help=None)

 

python アットマーク

・デコレータ

関数を修飾する関数

@デコレーター関数
def 修飾される関数():

def say_name():

print("I am Mike")

say_name = wrap(say_name)

↓ @で書き換え

@wrap

def say_name():

print("I am Mike")

 

アノテーション

注釈

▼関数アノテーションの書き方
1.関数の引数に期待する型は、引数の後に、コロン:を付けて示す。
2.戻り値に期待する型は、引数の閉じカッコの後に、矢印->を付けて示す。

 

str1 :str = 'Hello world!'
print(str1)

import datetime
def get_todays_date() -> str:
  dt_now = datetime.datetime.now()
  date :str = dt_now.strftime("%m月%d日")
  return date

today = get_todays_date()
print("今日は", today, "です")

Python 仮想環境の作り方

仮想環境の作成

PS> python -m venv .venv

 

権限の確認

PS> Get-ExecutionPolicy
Restricted

 

権限が制限されている場合

PS> Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

 

仮想環境の有効化

PS> .venv\Scripts\activate.ps1
(.venv) PS>

 

パッケージのインストール

(.venv) PS> python -m pip install <package-name>

 

仮想環境の無効化

(.venv) PS> deactivate
PS>

 

仮想環境を作る必要性

・システム汚染を回避する

・依存関係の競合を回避する

・再現性の問題を最小限に抑える

・回避インストール権限のロックアウト