【Python】 インスタンス変数を辞書型で出力 + JSON形式で文字列にする。
こんばんは、葛の葉です。
Pythonのインスタンス変数を辞書型で出力する方法とそれをJSONに変換する方法を記載します。
環境
Python 3.6.5
こんな感じ
class MyClass(object): def __init__(self, name): self.name = name self.gender = 'male' self._address = '192-1999' self.interest = ['Kemono Friends', 'DoDonpachi', 'Python'] self.age = 111 myclass = MyClass('kuzunoha')
このようにクラスとインスタンスを作成する。
print(myclass.__dict__)
myclass.__dict__
がインスタンス変数を辞書型として持っている。
{'name': 'kuzunoha', 'gender': 'male', '_address': '192-1999', 'interest': ['Kemono Friends', 'DoDonpachi', 'Python'], 'age': 111}
JSON形式文字列にする。
内部modulejson
のjson.dumps
を使ってJSON型にする。
import json # ここ追加になっている点に注意 class MyClass(object): def __init__(self, name): self.name = name self.gender = 'male' self._address = '192-1999' self.interest = ['Kemono Friends', 'DoDonpachi', 'Python'] self.age = 111 def to_json(self): return json.dumps(self.__dict__, ensure_ascii=False, indent=4) myclass = MyClass('kuzunoha')
json.dumps(self.__dict__, ensure_ascii=False, indent=4)
はjson
モジュールを使って辞書型をjsonに変更しています。
オプションのensure_ascii=False
はこれを打たないとバイト文字になってしまうので、そのようにしています。
indent=4
はインデントを空白4つで自動で行ってくれます。自動ってすごい。かしこい。
print(myclass.to_json())
で出力してみましょう。
{ "name": "kuzunoha", "gender": "male", "_address": "192-1999", "interest": [ "Kemono Friends", "DoDonpachi", "Python" ], "age": 111 }
上記の通り出ている。けれども、少し問題なのがアンダースコア_
で定義したインスタンス変数もそのまま出力されている点かも?
それが嫌なら、一度、インスタンス変数の辞書をコピーして、そこから_address
を抜き取ってみる?
def to_json(self): dicts = self.__dict__.copy() # 以下の要素はjsonには要らないので削除 dicts.pop('_address') return json.dumps(dicts, ensure_ascii=False, indent=4)
myclass = MyClass('kuzunoha') print(myclass.to_json()) { "name": "kuzunoha", "gender": "male", "interest": [ "Kemono Friends", "DoDonpachi", "Python" ], "age": 111 }
【Docker】Windowsで「curl」コマンド使いたい件について[byrnedo/alpine-curl]
お世話になっております。葛の葉です。
WindowsPowerShellにはInvoke-WebRequest
というLinuxのBASHでいうところのcurl
みたいなコマンドがついていて、何かHTTP系に色んなテストをしてみたいときなんかは有効です。しかし、curl
に慣れていたりするとコマンドが打ちにくい、結果もなんだかわかりにくい等、curl
がやっぱり使いたい、ってときがあります。
そんなときに便利なDockerImageがbyrnedo/alpine-curl
です。
使い方は書いてある通り
先のURLにも書いてありますが…まぁ書いておきます。
docker pull byrnedo/alpine-curl
先ず、DockerImageをダウンロードするため、上記のコマンドを打ちます。-t
オプションでタグを指定するのもよいと思いますが、まぁ気にしなくてもいいかなぁと思います。ダウンロードが終われば使用可能です。
docker run --rm byrnedo/alpine-curl (url)
このコマンドでHTTPのrequestを確認することができます。
なお、dockerの--rm
オプションは、コンテナを通してコマンドを実行し、そのコマンドが完了したときにそのコンテナを消す、というオプションになります。curl
コマンドは何回も使うはずなので、そのたびにコンテナのカスが溜まっていくことを防いでいるわけですね。
docker run --rm byrnedo/alpine-curl https://www.google.co.jp
Googleのサイトをcurl
で受け取ればソースコードを取得できます。あとはcurl
の操作そのまま使えるので調べて使ってみてみてくださいな。
なお、Win版のcurlもある模様
下記URLにあります。一番下のほうにWindows64bit用のリンクがあるので、それを落としてbin
フォルダ以下に環境変数PATHを通してあげましょう。PowerShellではcurl
コマンドがInvoke-WebRequest
にaliasされているので、curl.exe
ってコマンドになるか、あれこれ設定をしてあげなきゃあいけません。詳しくはググってもらったほうがいいかな。
参考
【Python】Scikitlearnの内LinearRegressionを使った値予測を行う
こんばんは、葛の葉です。機械学習ライブラリであるsklearnを使ってデータの学習と予測…と言いたいところなんだけど、なんだかいいデータがなくて、全く無造作なデータを学習させて予測するという意味のないことやってました。
環境
Anaconda 5.3.0
Python 3.7.0
numpy 1.15.1
pandas 0.23.4
jupyter 1.0.0
scikit-learn 0.19.2
適当なデータを使う。
tekito.csv
data1,data2,data3 22,62,73 22,66,61 76,58,26 35,60,43 35,30,100 61,35,97 50,62,48 87,94,86 95,33,34 35,58,32 79,84,20 82,15,92 50,66,37 62,89,74 53,51,65 74,80,75 89,27,80 100,62,78 97,77,79 88,37,54
data1,data2,data3は共に15から100の数値を適当出力する設定にしているだけなので、なんも意味を持ちません。
重回帰分析を使う
回帰分析のうち、目的変数に対して説明変数が2つ以上のものを重回帰分析といい、説明変数が1つの場合は単回帰分析と言うみたいです。
目的変数とは予測したいデータで今回はdata3
です。
説明変数とは目的変数を予測するために使うデータのことdata1
,data2
です。
data1
とdata2
を使ってdata3
を予測するというのが今回の目的です。
回帰分析については以下のWikipediaも参照。
説明変数のデータ
test.csv
data1,data2 35,77 60,43 45,53 64,65 81,21 90,33 100,46 50,18 30,32 29,60
このtest.csv
のdata1
,data2
を使ってdata3
に相当するデータを出力する。
JupyterNoteBookを使う
以下はJupyterNoteBook上でのコマンドになります。
ライブラリのインポート
import pandas as pd import numpy as np # 要らないかも from sklearn.linear_model import LinearRegression as LR
上記コードをセルに挿入してからShift + Enter
すると次のセルに移ります。
その時に何らかのエラーが出ればそれはライブラリのインポートが失敗していると思います。
from sklearn.linear_model import LinearRegression as LR
これが機械学習のライブラリsklearn
です。
LinearRegression
は線形回帰を意味しているようです。
as LR
としてLinearRegression
をLR
として略称します。
CSVのインポート
pandasでcsvをロードします。
train = pd.read_csv('tekito.csv') test = pd.read_csv('test.csv')
pandas.read_csv('***.csv')
はpandasのライブラリとしてcsvをpandasのDataFrameとして読み込みます。
Shift + Enter
で、次のセルへ。
エラーを吐く場合は事前に説明していたCSVが、同じディレクトリ内にないとか、その辺りだとおもいます。
train.head()
.head()
は読み込んだDataFrame
の最初の5行分を出力します。
data1 data2 data3 0 22 62 73 1 22 66 61 2 76 58 26 3 35 60 43 4 35 30 100
Shift + Enter
で、次のセルへ。
特定のカラムのデータを読み取る
trainX = train[['data1', 'data2']] y = train['data3'] testX = test[['data1','data2']]
train内の2つのカラムを代入しています。
train[['data1', 'data2']]
y
は目的変数としtrain['data3']
を代入しています。
testX
は最終的に予測するための説明変数をもっています。
trainX
とy
を使ってdata1
,data2
とdata3
で線形回帰を行い、最終的にはtestX
内にあるdata1
,data2
を元にtestXのdata3
に当たるデータを出力します。
Shift + Enter
で、次のセルへ。
モデルの作成とモデルへの学習
model = LR() model.fit(trainX, y)
model.fit(trainX, y)
で.fit(説明変数, 目的変数)
となっており、回帰モデルとなっています。
trainX
はdata1
とdata2
をもっているので重回帰モデルとなっています。
Shift + Enter
で、次のセルへ。
学習したデータを出力する
pred = model.predict(testX) pred
以下のデータが学習で出したデータになります。
array([55.80356749, 65.91988259, 62.42089327, 60.75553676, 72.7960059 ,70.4459384 , 67.91714972, 71.41497867, 66.58486472, 59.5950097 ])
さっぱり意味がないデータですけどね。
Shift + Enter
で、次のセルへ。
ついでにCSVとして出力しましょう。
tester = pd.DataFrame() tester[0] = pred tester.to_csv('cho_tekitou.csv', header=None, index=None)
.to_csv
関数にてcho_tekitou.csv
という名前で出力します。
ここまできていて言うのもなんだが
data1
とdata2
は無造作なデータで、当然、法則性なんてないです。なので、最終的なpred
の値はとても意味のないものになるはずです。
またpred
が正確にデータを予言できているかどうか、というのも保証できません。
とりあえず、データを出せてよかったねってレベルで今回は終わりです。
【Python】JupyterNotebook + matplotlibで折れ線グラフを出力する
今回はAnaconda + matplotlibを使って折れ線グラフを出力します。
プログラミングの環境
Anaconda 5.3.0
Python 3.7.0
numpy 1.15.1
pandas 0.23.4
matplotlib 2.2.3
jupyter 1.0.0
使うデータ
日本が統計を開始してから2017年までの交通事故の統計データ
前準備
データ分析によく使われるpandas
numpy
matplotlib
をライブラリとしてインストールしておく必要あります。
pandas
ライブラリはpythonの標準の配列機能より強力なものを使えます。
numpy
ライブラリは計算機能が強い。
matplotlib
ライブラリは図を表示するもの。
以上のライブラリが必要になります。
なお、今回はAnaconda5.3.0環境でのVersionになります。
Anacondaなら最初から3つのライブラリは入っています。
データを加工する
もともと入っているデータではちょっと表示がやりづらそうだったのでこんな感じで変更
和暦 =>(西暦に変換して) => AD 発生件数(件) => Incidents 負傷者数(人)=> Injured_person 死者数(人)=> Casualties
それ以外のものは削除しました。
これのデータをCSVとして変更しました。これらは
名前はh29_jiko.csv
です。
AD,Incidents,Injured_person,Casualties 1948,21341,17609,3848 1949,25113,20242,3790 1950,33212,25450,4202 。。。。
こんな感じ
jupyter notebook
コマンドにてjupyter notebookを起動しましょう。
(JupyterNotebookについてはまた今度)
最初のライン
import pandas as pd import numpy as np from matplotlib import pyplot as plt %matplotlib inline
%matplotlib inline
はJupyterNote上でmatplotlibを表示するための設定です。
上記のコードを入力した状態でShift + Enter
を押します。
ライブラリがうまくはいっていれば、問題なく次の行に進むはず。
2つ目のライン
jiko29 = pd.read_csv('h29_jiko.csv')
pd.read_csv()
はpandas
のcsvファイル
を読み込む関数です。
h29_jiko.csv
という名前でCSVファイルを同じディレクトリに保管しているので、このデータ呼び出し方で呼べます。
Shift + Enter
でそのコードを実行。
3つ目のライン
plt.plot(jiko29['AD'],jiko29['Incidents'])
Shift + Enter
でコード
と、このように簡単に折れ線グラフを出力できます。
2000年頭くらいから2010年くらいまでの事故数が増えて、それから右肩下がり?のようです。
3つ目のラインを編集
plt.plot(jiko29['AD'],jiko29['Injured_person'])
をグラフ内に追加します。(負傷者数)
plt.plot(jiko29['AD'],jiko29['Incidents']) plt.plot(jiko29['AD'],jiko29['Injured_person'])
このように、データを重ねて表示することも可能です。
一回の事故に対して、負傷者が増えたってこと…であってるのかな?
4つ目にやりたかったけど出来なかったこと
死亡者数のデータを出力しようとすると…
plt.plot(jiko29['AD'],jiko29['Incidents']) plt.plot(jiko29['AD'],jiko29['Injured_person']) plt.plot(jiko29['AD'],jiko29['Casualties'])
緑色のグラフが死者数…だけど、さっぱりデータがわからない。
このデータだけ見てみると経緯がわかりやすい。
死者数はだんだんと減っていっている傾向にある、ということ。
二つ軸グラフ
が使えればデータわかりやすかったんだと思うけど、ちょっと今はわからない。
また調べてやってみよう。
【Python】FlaskのJinja2と別でimportしたJinja2を使って文字の置換を二回行う
こんばんは、葛の葉です。
Flaskの文字置換を二段階にわけて行いたい場合の方法を書きます。
環境
python 3.6.5
flask 1.0.2
jinja2 2.10
やり方の説明
元のhtml
-> custom_jinja
-> flaskのjinja2
できれいにする。
custom_jinja
では::
で挟んだ変数を読み込む
flaskのjinja2
では{{}}
で挟んだ変数を読み込む
jinja2とjinja2.Environmentを使う
flask内のjinja2とは別
のjinja2を使用する。
その別のjinja2を便宜的にカスタムjinja
と呼ぶことにする。
jinja2.Environment()
内の引数にある以下の値を変更、それをカスタムjinjaというインスタンスとして扱う。
variable_start_string
は変数を囲う最初の文字
variable_end_string
は変数を囲う最後の文字
custom_jinja = jinja2.Environment( loader=jinja2.FileSystemLoader('templates'), variable_start_string=':', variable_end_string=':' )
説明が前後したけど、loader=jinja2.FileSystemLoader('templates')
はtemplateファイルを読み込むディレクトリ名をtemplates
にしています。
page = custom_jinja.get_template('index.html')
と、このようにすることで、templateファイルを読み込めます。
render_template = pages.render(variable_name='value')
と、することでvariable_nameの変数をtemplateファイルに送ることができます。
こんな感じ
sandbox_flask.py templates/ ├index.html └layout.html
sandbox_flask.py
from flask import Flask, render_template, render_template_string import jinja2 app = Flask(__name__) custom_jinja = jinja2.Environment( # 元htmlの保存されているディレクトリ名。flaskと併用するので以下の値。 loader=jinja2.FileSystemLoader('templates'), #デフォルトでは{%にあたるもの。flaskのjinjaと重複しない値にする。 block_start_string='[{[{[Q', #デフォルトでは%}にあたるもの。flaskのjinjaと重複しない値にする。 block_end_string='Q]}]}]', # このvariable...と続くステータスを挟みたい文字にする。 variable_start_string=':', variable_end_string=':', # オートエスケープは特殊文字等をエスケープします。 autoescape=False) # 定数のようなもの。:Key: -> Value にしてくれる。 SPECIAL_CONVERSION_CHARACTER = { 'test': '!TesT!' } # SPECIAL_CONVERSION_CHARACTERが不要ならここの処理も不要 custom_jinja.globals.update(SPECIAL_CONVERSION_CHARACTER) @app.route("/") def hello(): # index.htmlを元にhtmlを生成します。 page = custom_jinja.get_template('index.html') template = page.render(name='サンプルタイガー') return render_template_string(template, name='サンプルドラゴン', title='Titleだよ!!!') if __name__ == "__main__": app.run(debug=True)
layout.html
<!doctype html> <html> <head> <meta http-equiv="content-type" charset="utf-8"> <title>{{ title }}</title> </head> <body> {% block content %} {% endblock %} </body> <footer> </footer> </html>
index.html
{% extends "layout.html" %} {% block content %} <p> :':name:':=:name:<br> {{ '{{ name }}' }}={{ name }}<br> </p> :test: {% endblock %}
表示はこんな感じ
:name:=サンプルタイガー {{ name }}=サンプルドラゴン !TesT!
STR型を変換する
bunsho = ':one:である :two:なのだ'
以下のような辞書を参照してAである Bなのだ
という文字列にしたい場合
{'one': 'A','two': 'B'}
importやcustom.jinjaなどの記載省略 ... @app.route("/") def hello(): ...省略... @app.route("/x") def xstring(): string = custom_jinja.from_string(':one:である :two:なのだ ') strings = string.render( { 'one': 'A', 'two': 'B' } ) return render_template('strings.html', strings=strings) ...
strings.html
( {{ strings }}と書かれているだけのhtml)
{{ strings }}
出力するとこうなる
Aである Bなのだ
出来なかった個所
key名が数字のみ場合は参照されない。
string = custom_jinja.from_string(':1:である :2:なのだ ') strings = string.render( { '1': 'A', '2': 'B' } ) return render_template('strings.html', strings=strings)
-> 1である 2なのだ
【Python】数字をprint()する時、整数か文字列かがわからなくて困る件について repr()
お世話になっております。
葛の葉です。
標題の件につきまして、解決方法がわかりましたので、ご連携いたします。
なんかもう挨拶が面倒なので、次からはこんなスタンスにしたいです。
Pythonの環境について
Python 3.6.5
事の発端
プログラミングをしているとprint()
を使って値がちゃんと出ているかどうか確認したいなぁって思ったりしますね。
例えば遷移する変数の値を見てみたい、なんて時なんかはprint()で見ていきたいですよね。
nana = 7 shichi = '7' print('nana={}'.format(nana)) print('shichi={}'.format(shichi))
nana
は7
でshichi
は'7'
が返ってくると思うじゃあないですか?結果は以下の感じなんですよ。
nana=7 shichi=7
shichi='7'
になってほしかったですね。これだけ見るとshichi
も整数と勘違いしてしまうかも。
repr()で解決
print()で変数を囲う前にrepr()で変数を囲ってあげればよいです。以下の感じ。
nana = 7 shichi = '7' print('nana={}'.format(repr(nana))) print('shichi={}'.format(repr(shichi)))
出力は以下の感じ
nana=7 shichi='7'
repr()についての公式ドキュメント
以下が公式ドキュメント
2. 組み込み関数 — Python 3.6.5 ドキュメント
コマンドライン上ではどうか?
Python 3.6.5 (default, Jun 27 2018, 08:15:56) [GCC 6.3.0 20170516] on linux Type "help", "copyright", "credits" or "license" for more information. >>> nana = 7 >>> shichi = '7' >>> >>> nana 7 >>> shichi '7' >>> repr(nana) '7' >>> repr(shichi) "'7'" >>> 'nana={}'.format(repr(nana)) 'nana=7' >>> 'shichi={}'.format(repr(shichi)) "shichi='7'"
ちなみにドキュメントにも書いてある通り、この子たちはstr
のようです。
>>> type(repr(nana)) <class 'str'> >>> type(repr(shichi)) <class 'str'>
【Python】かんたんassertテストをしてみる
こんにちは、葛の葉です。
assert
を使って簡単なテストをしてみましょう。
Python実行環境
Python 3.6.5
assertの使い方
assert 条件式, '間違ったときに出力される文字列'
assert
と条件式
の間は半角スペースなんですよ。Pythonでは珍しくパレンティスの括弧を使わないで引数を指定しているような気がします。
パレンティスの括弧はこの子 -> ()
こんな感じ
def arry_to_str(arry): ''' 引数で受け取ったarryを配列っぽい形でstrにして返します。 arry_to_str([i1,i2,i3,.....]) -> '["i1","i2","i3",.....]' 要素は""で囲われます。 ''' moji = '[' for i in arry: moji += '"{}"'.format(i) if i != arry[-1]: moji += ',' moji += ']' return moji arry = ['yum', 'npm', 'apt'] test_str = '["yum","npm","apt"]' assert test_str == arry_to_str(arry), 'まちがってるぜ'
これで実行しても何も返らない。成功しているので特に返り値がないみたい。失敗しているとエラー文が返され、実行されたプログラムはそこで終了する。
逆に言えばassert
が問題なく実行されれば、処理は続行されることになる。誤った処理などを弾くのに向いているかも知れない。
assertを失敗させる
17行目を以下のように変更する。
test_str = "['yum','npm','apt']"
各要素をダブルクォーテーション""
で囲っている部分をシングルクォーテーション''
に変更する。そうすると…
Traceback (most recent call last): File "d.py", line 19, in <module> assert test_str == arry_to_str(arry), 'まちがってるぜ' AssertionError: まちがってるぜ
このように期待通り失敗する(?)