20210909のPythonに関する記事は30件です。

Qiitaの記事をバックアップする(Python)

QiitaではAPIが公開されているので、これを利用して記事をバックアップします。 1. QiitaのAPIを利用する Qiitaのアクセストークンを取得する Qiitaにログインした状態で、[設定] - [アプリケーション]にアクセスします。 個人用アクセストークンの「新しくトークンを発行する」をクリックします。 アクセストークンの説明を入力し、read_qiitaにチェックを入れ、「発行する」ボタンをクリックします。 アクセストークンが表示されるので、控えておきます。 APIを使用する 投稿した記事一覧を取得するにはGET /api/v2/authenticated_user/itemsのリソースを使用します。 PostmanなどのAPIクライアントを使用してQiita APIを叩きます。 ヘッダーにAuthorization: Bearer {qiitaで取得したアクセストークン}を追加します。 Bearerとアクセストークンの間に半角スペースが必要です。 下記のようなレスポンスがかえってきます。bodyにマークダウンの本文が設定されています。以下ではこれをPythonで取得するプログラムを作成します。 [ { "rendered_body": "\n<h2>\n<span id=\"apex-pmdとは\" class=\"fragment\"></span>...", "body": "## Apex PMDとは\nApex PMDはApexのソースコードを静的解析...", "coediting": false, "comments_count": 0, "created_at": "2021-09-01T00:30:21+09:00", "group": null, "id": "d85a93009acefceaf10d", "likes_count": 2, "private": false, "reactions_count": 0, "tags": [ { "name": "Salesforce", "versions": [] }, { "name": "Apex", "versions": [] }, ], "title": "[Apex PMD] VSCodeでApexの静的解析を行う", "updated_at": "2021-09-01T00:30:21+09:00", "url": "https://qiita.com/TaaaZyyy/items/d85a93009acefceaf10d", // 略 2. Pythonでバックアップツールを実装する 下記の「FILL_ME_IN」をアクセストークンに置換して実行するとバックアップできます。 qiita_backup_tool.py #!/usr/bin/python ########################################################################################## # SECURITY_TOKENにQiitaのアクセストークンを設定してください。 SECURITY_TOKEN = 'FILL_ME_IN' DIRECTORY_NAME = 'output' ########################################################################################## import urllib.request import json import os import shutil from datetime import datetime from io import BytesIO # download function def download_qiita(): print('Qiita記事のバックアップを開始します。') dir = DIRECTORY_NAME # バックアップフォルダをリフレッシュ if os.path.exists(dir): shutil.rmtree(dir) os.makedirs(dir) # 一度に100件までしか取得できないため、ループで処理する for i in range(100): # Qiita記事を取得 url = 'https://qiita.com/api/v2/authenticated_user/items' url += '?page=' + str(i + 1) + '&per_page=100' headers = {'Authorization' : 'Bearer ' + SECURITY_TOKEN} req = urllib.request.Request(url, None, headers) res = urllib.request.urlopen(req) items = json.load(res) res.close if not items: break # Qiita記事をマークダウン形式で保存 for item in items: body = item['body'] private = item['private'] qiita_id = item['id'] title = item['title'] tags = item['tags'] created_at = item['created_at'] updated_at = item['updated_at'] # 公開記事と限定公開記事のフォルダを分ける subDir = dir + '/private' if private else dir + '/public' if not os.path.exists(subDir): os.makedirs(subDir) # マークダウンで保存 file = open(subDir + '/' + create_filename(title, created_at), 'w', encoding='utf-8') file.write(create_info(title, tags, created_at, updated_at) + body) print('バックアップが完了しました。') def create_info(title, tags, created_at, updated_at): # ファイルの冒頭にメタデータを追加する info = '---\n' info += 'title: ' + title + '\n' info += 'tags: ' for tag in tags: info += tag['name'] + ' ' info += '\n' info += 'created_at: ' + created_at + '\n' info += 'updated_at: ' + updated_at + '\n' info += '---\n' return info def create_filename(title, created_at): # ファイル名に「作成日_タイトル」を使用する filename_date = format(datetime.strptime(created_at, '%Y-%m-%dT%H:%M:%S%z'), '%Y%m%d') # ファイル名に使用できない文字列を置換する filename_title = title.replace('\\', ' ') filename_title = filename_title.replace('/', ' ') filename_title = filename_title.replace(':', ' ') filename_title = filename_title.replace('*', ' ') filename_title = filename_title.replace('?', ' ') filename_title = filename_title.replace('"', ' ') filename_title = filename_title.replace('<', ' ') filename_title = filename_title.replace('>', ' ') filename_title = filename_title.replace('|', ' ') return filename_date + '_' + filename_title + '.md' download_qiita() 下図のようにバックアップファイルが作成されていきます。 メタデータはファイルの冒頭に追加されます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Python】ジャンケンのプログラムを作ってみた!

 Pythonを勉強し始めて1週間が経過したので、何か簡単なプログラムを作ってみようと考え、ジャンケンのプログラムを作ってみました。 import random while True: jan = ["グー","チョキ","パー"] cpu = random.choice(jan) user = int(input("グーだったら0、チョキだったら1、パーだったら2を入力してください:")) print("あなた:" + jan[user]) print("CPU:" + cpu) if jan[user] == cpu: print("あいこです") continue else: if cpu == jan[user - 1]: print("負けです") break else: print("勝ちです") break  出力結果は以下のような形です。 グーだったら0、チョキだったら1、パーだったら2を入力してください:0 あなた:グー CPU:グー あいこです グーだったら0、チョキだったら1、パーだったら2を入力してください:2 あなた:パー CPU:グー 勝ちです  何も調べずに自分の知識の範囲内でこのようなコードを書きましたが、ジャンケンの仕組みやPythonのメソッドをもっと考えれば、より良いコードが書けると思いますので、ご意見いただけるとありがたいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Python3について(return[戻り値]について)

returnについて 関数の最後にいつも書いてありましたが、あまり意味は分かっていませんでした。 なんとなく理解したので、覚書的に書いておきます。 1.returnがない場合 def aisatsu(): print('Hello') x = aisatsu() #xに対して、あなたは今後aisatsu()ですよと指示している >> Hello print(x) #xがaisatsu()になっていれば、Helloが出力されるはず >> None このようにxにaisatsuを割り当てて、xを呼び出してもHelloはプリントされません。 なぜなら、このaisatsuの関数が直接呼ばれた時でないと関数の中身が動かないからです。 なので、xに関数を割り当ててもdef aisatsu():までしか呼び出されません。(※イメージです) 2.returnをつけた場合 def aisatsu(): print('Hello') return ('Hello') #別の名前で呼ばれた時はこれを返してね x = aisatsu() #xに対して、あなたは今後aisatsu()ですよと指示している >> Hello print(x) >> Hello returnをつけると、その関数が別の名前で呼ばれた時は、returnの値を返す。 なので、returnの中を変えると以下のようになる。 def aisatsu(): print('Hello') #正規の名前ならこっち return ('Bay') #別の名前で呼ばれたらこっち x = aisatsu() #xに対して、あなたは今後aisatsu()ですよと指示している >> Hello print(x) >> Bay print(x)では、別の名前で呼ばれたので、returnの中身を返している。 returnの中身は計算結果などを保存できるので、次のようなこともできる。 3.計算結果を保存 returnの結果は記憶されるので持ち越すことが出来る。 returnを消すと、計算結果すら出力されなくなる。なぜなら、addはx*xを中でやっているだけで、 printすらしていないので、内部で計算して満足して終わりになります。 def add(x): return (x*x) z = add(3) #zに3×3が記憶される(つまり9) print(z) >> 9 y = add(z) #zに9が記録されているので、9×9になる print(y) >> 81 4.最後に 計算結果をどこかで使おうとするのであれば、returnを使い、その関数の結果として何を返すのかを明確にする必要がある。ということを学びました。 最後にreturnが無いと大変だよという例をあげておきます。 def add(x): print(x*x) return('Hello') #関数名以外で呼ばれた時はこれを返す z = add(3) #関数名で呼ばれているので3×3がプリントされる >> 9 print(z) #関数名以外で呼ばれているので、戻り値のHelloがプリントされる >> Hello
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

物体検出のためのアノテーション作業・データ拡張

機械学習や深層学習を学び始めて2か月の者です。 Yolo v3による物体検出を行う際に、準備作業としてアノテーションやデータ拡張を行う必要があったのですが、自分がやりたかったことや自分の使用している環境に完全に合致した記事が見当たらなかったので、せっかくなので自分が取り組んだ内容を備忘録として残すことにしました。 より良い案がありましたらご意見・アドバイス頂けましたら幸いです。 はじめに 物体検出の基本事項について簡単に触れておきます。 物体検出とは 写真や動画データの中から犬や猫などの物体を検出し、検出した物体の周囲を四角い箱(バウンディングボックス)で囲う深層学習の手法のことです。 アノテーションとは 物体検出を行うための深層学習モデルを作るに当たり、「これは犬だよ」「これは猫だよ」といった感じで画像データ内のオブジェクトの周りをバウンディングボックスで囲ってやり、それをモデルにインプットして学習させる必要があります。アノテーションとは、そのバウンディングボックスを手作業で画像に付与する作業のことを指します。 データ拡張とは 深層学習モデルの学習の際に使用する教師データが少ない場合に、データの水増しのために画像を少し拡大/縮小したり、あるいは回転したりするなどの加工を行う作業のことを指します。 やったこと 主に下記の作業になります。 【作業1】アノテーション作業 これには「labelImg」というツールを使用しました。このツールを使ってjpg等の画像ファイルに手作業でバウンディングボックスを囲ってやることで、そのボックスの座標情報を含んだXMLファイルが生成されます。今回私が使用した環境では、「Pascal VOC」というフォーマットで作成しました。 (使用方法 参考:https://note.com/npaka/n/nf74e32b47712) 【作業2】アノテーションで作成したXMLファイルの取り込み これには、Pythonに組み込まれている「xml.etree.ElementTree」というXML読み込み用のライブラリを用いて、XMLファイル内のバウンディングボックスの情報をPythonプログラムに読み込ませました。 読み込むための処理は、下記サイトのサンプルコードを参考にさせて頂きつつ、自分がやりたいように少しカスタマイズしました。 (参考:http://maruo51.com/2020/06/05/pascalvoc_dataset/) 【作業3】データ拡張作業 データ拡張処理に使用できるライブラリとしては、TensorFlowに備わっている「ImageDataGenerator」が有名かと思いますが、ここでは上記のアノテーション作業によって画像に付与されたバウンディングボックスの情報ごとデータ拡張したかったため、代わりに「Albumentations」というライブラリを使用しました。 【作業2】でXMLファイルから取り込んだバウンディングボックスの座標情報とオリジナルの画像データをこのAlbumentationsのAPIにインプットすることで、画像データに拡大/縮小等の加工を加えた際にそれに合わせてバウンディングボックスの座標も変換されます。 (Albumentations公式サイト:https://albumentations.ai) なお、画像データをバウンディングボックス付きで表示させるための関数もAlbumentationsの公式サイトに記載されていますので、こちらを活用させて頂きました。(ただし、オリジナルのコードはcoco形式に対応したものだったため、Pascal VOC形式に対応するように一部コードを修正しました) (参考:https://albumentations.ai/docs/examples/example_bboxes/) ソースコード 上記の【作業1】はGUIツールを用いてバウンディングボックスを手作業で付与していくため、ソースコードはありません。ここでは、【作業2】と【作業3】に相当するソースコードを記載します。 【作業2-1】アノテーションで作成したXMLファイルを取り込むためのクラス定義 import xml.etree.ElementTree as ET class xml2list(object): def __init__(self, classes): self.classes = classes def __call__(self, xml_path): ret = [] xml = ET.parse(xml_path).getroot() for i in xml.iter("filename"): filename = i.text for size in xml.iter("size"): width = float(size.find("width").text) height = float(size.find("height").text) for obj in xml.iter("object"): difficult = int(obj.find("difficult").text) if difficult == 1: continue bndbox = [filename, width, height] name = obj.find("name").text.lower().strip() bbox = obj.find("bndbox") pts = ["xmin", "ymin", "xmax", "ymax"] for pt in pts: cur_pixel = float(bbox.find(pt).text) bndbox.append(cur_pixel) label_idx = self.classes.index(name) bndbox.append(label_idx) ret += [bndbox] return np.array(ret) # [filename, width, height, xmin, ymin, xamx, ymax, label_idx] 上記のコードは、一つの画像データに犬や猫等のオブジェクトのうち、いずれか一つだけ写っている場合のみに対応しています。複数のオブジェクトのバウンディングボックス情報が1つのXMLファイル内に存在する場合は、コードの改良が別途必要になります。 【作業2-2】XMLファイル取り込み import glob xml_paths = glob.glob("(XMLファイルが格納されているフォルダのパス)/*.xml") category_names = ["dog", "cat"] # カテゴリ名のリスト(XMLファイル内の<name>タグに記載されているカテゴリ名) # XML取り込み用のクラスをインスタンス化 transform_anno = xml2list(category_names) # 試しに先頭のXMLファイルの内容を読み込んでみる(下記コメントのような出力が得られればOK) transform_anno(xml_paths[0]) # array([['cat.1.jpg', '300.0', '280.0', '32.0', '23.0', '300.0', '280.0', '1']], dtype='<U9') 【作業2-3】XMLファイルから取り込んだデータをDataFrame化 df = pd.DataFrame(columns=["filename", "width", "height", "xmin", "ymin", "xmax", "ymax", "category_id"]) for path in xml_paths: bboxs = transform_anno(path) for bbox in bboxs: tmp = pd.Series(bbox, index=["filename", "width", "height", "xmin", "ymin", "xmax", "ymax", "category_id"]) df = df.append(tmp, ignore_index=True) df = df.set_index("filename") df = df.sort_values(by="filename", ascending=True) display(df) 上記のコードが問題なく実行できれば、各画像ファイルに対するバウンディングボックスの情報を含んだ下記のようなデータフレームが表示されるはずです。 上記のデータフレームの「category_id」列の数値ですが、これはcategory_names変数(=["dog", "cat"] )のインデックス番号をカテゴリのIDとして割り当てるようxml2listクラス内で処理しています。 【作業3-1】画像データをバウンディングボックス付きで表示する関数の定義 import random import cv2 from matplotlib import pyplot as plt BOX_COLOR = (255, 0, 0) # Red TEXT_COLOR = (255, 255, 255) # White def visualize_bbox(img, bbox, class_name, color=BOX_COLOR, thickness=2): """Visualizes a single bounding box on the image""" x_min, y_min, x_max, y_max = bbox # バウンディングボックス形式:pascal_voc x_min, y_min, x_max, y_max = int(x_min), int(y_min), int(x_max), int(y_max) # バウンディングボックス形式:pascal_voc # 左上の座標(x_min, y_min)から右下の座標(x_max, y_max)までの長方形を描画(=バウンディングボックス) cv2.rectangle(img, (x_min, y_min), (x_max, y_max), color=color, thickness=thickness) ((text_width, text_height), _) = cv2.getTextSize(class_name, cv2.FONT_HERSHEY_SIMPLEX, 0.35, 1) cv2.rectangle(img, (x_min, y_min - int(1.3 * text_height)), (x_min + text_width, y_min), BOX_COLOR, -1) # 画像データ中のバウンディングボックスにクラス名のテキストを追加 cv2.putText( img, text=class_name, org=(x_min, y_min - int(0.3 * text_height)), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.35, color=TEXT_COLOR, lineType=cv2.LINE_AA, ) return img def visualize(image, bboxes, category_ids, category_id_to_name): img = image.copy() for bbox, category_id in zip(bboxes, category_ids): class_name = category_id_to_name[category_id] img = visualize_bbox(img, bbox, class_name) plt.figure(figsize=(12, 12)) plt.axis('off') plt.imshow(img) 【作業3-2】データ拡張実行 import os import albumentations as A # 使用したalbumentationsのバージョン:1.0.3 # (上記以外のバージョンだと下記のA.Compose辺りでエラーになるかも) # データ拡張 定義 transform = A.Compose([ A.HorizontalFlip(p=1), # 水平方向移動 A.ShiftScaleRotate(p=1), # 回転 A.RandomBrightnessContrast(p=1), # コントラスト変更 A.RGBShift(r_shift_limit=30, g_shift_limit=30, b_shift_limit=30, p=1), #RGB変更 ], bbox_params=A.BboxParams(format='pascal_voc', label_fields=['category_ids']), ) jpg_paths = "(jpgファイルの入ったフォルダのパス)" flist = os.listdir(jpg_paths) # jpgファイルの一覧のリスト image_list = [] # jpgファイルをndarray化したものを詰め込むためのリスト category_id_to_name = {0: 'dog', 1: 'cat'} # カテゴリのIDと名称の対応表 # フォルダ内のjpgファイルを順番にデータ拡張し、バウンディングボックス付きで可視化 for jpg_file in flist: print(jpg_file) image = cv2.imread(jpg_paths + "/" + jpg_file) image_list.append(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) # バウンディングボックスの座標データを取得 bboxes_temp = list(df.loc[jpg_file, ["xmin", "ymin", "xmax", "ymax"]]) print(bboxes_temp) bboxes = [tuple([float(bbox) for bbox in bboxes_temp])] # カテゴリIDを取得 category_ids = [int(df.loc[jpg_file, "category_id"])] # print(image_list[-1]) print(bboxes) print(category_ids) # データ拡張実行 transformed = transform(image=image_list[-1], bboxes=bboxes, category_ids=category_ids) # データ拡張後の画像を表示 visualize( transformed['image'], transformed['bboxes'], transformed['category_ids'], category_id_to_name ) 上記処理はデータ拡張した画像を可視化するところまでで終わっており、データ拡張後の画像データの保存は行っていません。 さいごに 以上、物体検出のための前準備として、labelImgによるアノテーションとAlbumentationsによるデータ拡張作業の一連の流れについて説明しました。 少しでもご参考にして頂けましたら幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

本:問題解決のPythonプログラミング

「問題解決のPythonプログラミング ―数学パズルで鍛えるアルゴリズム的思考」を読んだのでまとめてみました! 著者:Srini Devadas 翻訳:黒川 利明 出版社:オライリージャパン 発売日:2018/9/22 まとめ 有名なアルゴリズムの本はC++で書かれているものが多く、pythonで学べる本を探していたところ当書を見つけました。 原書がMITから出されており恐れていましたが、atcoder灰色の僕でも頑張れば読めるレベルでした。 ただ、他のレビューにもある通り読みづらさは少しあります。 (訳がわかりにくい?) 全21章から構成され、それぞれの章で一つの「問題」が設定されています。 「問題」に関しては無機質なものでなく、面白い設定がされています。飽きずに最後まで取り組めます。 流れは最初に思いつきそうなアルゴリズムを示してから綺麗なアルゴリズムを紹介してくれます。 その後に練習問題が3題ほど出題されます。 サンプルコードはMITサイトのCode for Selected Puzzle Solutionsから落としてこれます。(python3対応) が、残念なことに練習問題の解答がついていませんでした。 わからない問題の答えがないのでかなりストレスになります。 前半は基本的な文法がわかれば比較的容易に解けると思います。 後半は再帰を使わないと解けないので難しく感じました。 ただ、問題の設定が面白いので最後まで読み切れると思います(問題が全部解けるかは別です)。興味がわけばぜひ! 以下当書で学べるアルゴリズムを自分なりにまとめます。 学べたこと 1.二分探索 2.bit全探索 3.再帰 4.マージソート 5.クイックソート 6.深さ優先探索 7.幅優先探索 1-二分探索 ソート済みの配列から任意の要素を探索する一番有名?なアルゴリズム。 単純なループ処理で見つけりとO(N)かかるところをO(logN)で求めることができる! 応用が効くのでアルゴリズム入門にGOOD! 方針 1.配列の中間の要素と調べたい要素の大小を調べる 2-a.調べたい要素の方が大きければ探索範囲を(中間~最後)の範囲に絞る 2-b.調べたい要素の方が小さければ探索範囲を(最初~中間) の範囲に絞る >1,2の繰り返し 実装 array = [1,2,3,4,5,6,7,8,9] target = 9 top = len(array) - 1 bottom = 0 while top >= bottom: middle = (top + bottom) // 2 if array[middle] < target: bottom = middle + 1 elif array[middle] > target: top = middle - 1 elif array[middle] == target: print(f'{middle + 1}番目に発見!') break else: print('存在しない!') 2-bit全探索 「9章アメリカズ・ゴット・タレント」で出てくる。 名前の通り全探索です。組み合わせの全列挙とかで使える。 計算量が指数的O(2**N)に増えるので N=20~30ぐらいが限界だが、bitの勉強にもなるのでコスパよし! 問題 atcoderからお借りします https://atcoder.jp/contests/abc045/tasks/arc061_a こちらを参考にしました https://qiita.com/hareku/items/3d08511eab56a481c7db 方針 入力された数字(s)とsの間(len(s)-1)と考える sの間をbit探索して1なら'+', 0だと何も入れない。 作った式を都度計算して結果を足していく 上記全パターンを探索する 実装 s = '125' answer = 0 # bitに変換して探索 for i in range(2 ** (len(s)-1)): formula = [''] * len(s) for j in range(len(s)): if i >> j & 1: formula[len(s)-j-2] = '+' else: formula[len(s)-j-2] = '' calc = '' for i, j in zip(s, formula): calc += i + j answer += eval(calc) print(answer) 3-再帰 関数の中で自分を呼び出す処理をする。 当書の目玉! 後半は再帰を使わないとほとんど解けないが、理解が難しく苦戦したポイント。 単純な再帰だと計算量が多くなりすぎるのでメモ化と併用されることが多い。 問題 フィボナッチ数列を再帰で求める *フィボナッチ数列:数列のi番目がi-1番目とi-2番目の和になっている数列 0, 1, 1, 2, 3, 5, 8, 13, 21 方針 基底部分を決める。今回は配列の0番目と1番目を基底部にする。 i-1とi-2の和をひたすら再帰 i番目をメモしておくと効率が良い 実装 idx = 30 #30番目のフィボナッチ数を求める def recursiveFibonacci(idx, memo = {}): if idx <= 0: return 0 if idx == 1: return 1 if not idx in memo: memo[idx] = recursiveFibonacci(idx-1, memo) + recursiveFibonacci(idx-2, memo) return memo[idx] print(recursiveFibonacci(idx-1)) 4-マージソート 「11章 中庭にタイルを敷く」で出てくる。 ソートアルゴリズムのうちの一つ 最小要素まで2分割してソートしたものを結合していく。 一般に計算量O(N*logN)と高速だが、メモリを大量に使うのが欠点 方針 再帰で実装する。 1. 基底部を書く。今回は要素が二つ以下の時に二要素をソートする 2. 配列を二分割する 3. 二分割した配列をソートしながらマージ 4. 2,3を再帰 実装 from random import sample def mergeLst(left, right): merged_lst = [] l = 0 r = 0 while l < len(left) and r < len(right): if left[l] <= right[r]: merged_lst.append(left[l]) l += 1 else: merged_lst.append(right[r]) r += 1 if l < len(left): merged_lst += left[l:] elif r < len(right): merged_lst += right[r:] return merged_lst def mergeSort(lst): if len(lst) <= 1: return lst if len(lst) == 2: if lst[0] >= lst[1]: lst = [lst[1], lst[0]] return lst middle = len(lst) //2 left = mergeSort(lst[:middle]) right = mergeSort(lst[middle:]) return mergeLst(left, right) # ランダムな配列を作成 lst = sample(range(100), k=15) print(mergeSort(lst)) 5-クイックソート 「13章 整理が苦手な修理屋」で出てくる。 pivotを決めてそれより大きい要素と小さい要素に分けていく。 参考:https://tech-shelf.hatenablog.com/entry/algorithm/quicksort 一般に計算量O(N*logN)と高速。 マージソートと違い、元のリストだけを並び替えていくのでメモリに優しい。 関係ないがpythonの組込sort関数はティムソートと呼ばれるアルゴリズムらしい。 方針 再帰で実装する。 元のリストを並び替えていくことに注意! 1. 基底部を書く。今回は要素数が1の時に再帰処理を終了 2. pivotを決める 3. pivotより大きい要素と小さい要素に分ける処理を作成 4. それぞれの要素に関して再帰 実装 from random import sample def divided(lst, start, end): pivot = lst[end] # startを3個目のループで参照したいので最初に-1をする start -= 1 done = False while not done: while not done: start += 1 if start >= end: done = True break if lst[start] > pivot: lst[end] = lst[start] break while not done: end -= 1 if start >= end: done = True break if lst[end] < pivot: lst[start] = lst[end] break lst[end] = pivot return end def quickSort(lst, start, end): if start >= end: return lst pivot_idx = divided(lst, start, end) quickSort(lst, start, pivot_idx - 1) quickSort(lst, pivot_idx + 1, end) return lst # ランダムな配列を作成 lst = sample(range(100), 15) print(quickSort(lst, 0, len(lst)-1)) 6-深さ優先探索 「19章 忘れられない週末」で出てくる。 グラフの探索に使うアルゴリズム。 1. ノードがなくなるまで探索 2. 分岐に戻る 1, 2の繰り返し。 実装は再帰で行う他にstackで管理するやり方もある。 問題 グラフが2部グラフかチェックするコードを書く 2部グラフ:グラフを2分割したとき集合の中で頂点が隣接しないグラフ 参考:https://ja.wikipedia.org/wiki/2部グラフ グラフは無向グラフで辞書型で与えられるとする。 keyにノードの名前。 valueに隣接関係を示す。 {'A': ['B', 'D'], 'B': ['C', 'A'], 'C': ['D', 'B'], 'D': ['A', 'C']} 方針 グラフを色分けした時に2色(red, blue)だけで表現することができるか確かめる 2色で表現できる=>2部グラフ 表現できない=>2部グラフでない 再帰でノードを探索していく 基底部を考える。 色を塗ってないノードに達した時、色を塗る 色が既に塗ってあるノードに達した時 塗る予定の色が同じ色ならスキップ 塗る予定の色と違う色なら2部グラフでない ルートのノードを決めて探索開始 すべての探索が問題なく終わると2部グラフであることがわかる 実装 graph = {'A': ['B', 'D'], 'B': ['C', 'A'], 'C': ['D', 'B'], 'D': ['A', 'C']} def changeColor(color): if color == 'red': return 'blue' else: return 'red' def dfs(graph, start, color, memo = {}): if not start in memo: memo[start] = color color = changeColor(color) else: if memo[start] == color: color = changeColor(color) return True else: return False for node in graph[start]: result = dfs(graph, node, color, memo) if not result: return '二部グラフじゃない!' return '二部グラフ!!!' root = 'A' color = 'red' print(dfs(graph, root, color)) 7-幅優先探索 「20章 6次の隔たり」で出てくる。 深さ優先探索と似ている。 最短経路を見つける時には幅優先探索を使った方が良い。 1. 一番近いノードをすべて探索する 2. 二番目に近いノードをすべて探索する ... n. n番目に近いノードをすべて探索する メモ:再帰で実装するのは難しそう? 問題 グラフのルートから各ノードへアクセスするためのステップ数を求める。 グラフは無向グラフで辞書型で与えられるとする。 keyにノードの名前。 valueに隣接関係を示す。 {'A': ['B', 'D'], 'B': ['C', 'A'], 'C': ['D', 'B'], 'D': ['A', 'C']} 方針 探索したノード、探索するノードをそれぞれvisited, frontearとして管理 1. ルートノードから探索を始める。 1-a. 初めて探索するノードならメモに保存。次に探索するノードに隣接ノードを追加する。 1-b. 探索済ノードなら何もしない 2. frontearが存在しなくなるまで探索する。 実装 graph = {'A': ['B', 'D'], 'B': ['C', 'A'], 'C': ['D', 'B'], 'D': ['A', 'C']} def bfs(graph, start, memo = {}): visited = set() frontear = set() step = 0 frontear.add(start) while len(frontear) > 0: new_frontear = set() for node in frontear: if not node in visited: visited.add(node) if step in memo: memo[step] += [node] else: memo[step] = [node] for child_node in graph[node]: new_frontear.add(child_node) frontear = new_frontear step += 1 return memo root = 'A' print(bfs(graph, root))  まとめ2 とりあえずいろいろまとめましたが、効率悪いところが多いかと思います。 今後も勉強を続けて加筆修正していきたい。。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Optiver Realized Volatility Prediction 簡単なコンペ詳細とEDA

はじめに Kaggleで9月末まで行われているコンペOptiver Realized Volatility Predictionについて簡単にどんな内容なのか日本語でまとめます。英語の説明読むのが大変というのと、どんなデータで何を予測するのか簡単に書いてあるサイトがなかったのでこれから参加される方や参加中に方の参考になれば幸いです。 Kaggleリンク 何を求めるのか 今回のコンペの依頼主はアメリカの電子マーケットメーカーであるOptiverという会社です。 Optiverは、世界中の多数の取引所でオプション、ETF、現金株式、債券、外貨へのアクセスと価格を改善といった業務を行なってます。 なので今回のコンペでは株価市場についてのコンペになります。 私も取り組むまで全く株価市場について知らなかったので、取組前はかなり身構えました。 長くなってしまうので結論からいうと今回のコンペの目的変数はボラティリティと呼ばれる指標です。 ボラティリティについて 見慣れない単語ですが、日本語でようやくすると株価の変動量(業界では流動性)のことです。上がったり下がったりする株価がどれくらい激しく動いているのかといった指標になります。 未来10分間のボラティリティを予測します。 ではなぜ企業がこれを予測するかというと、流動性が高いと取引回数が多くなり手数料等で利益が上がるからだと考えられます。 評価方法 作成したモデルは、トレーニング後の3ヶ月間の評価期間に収集した実際の市場データと比較して評価されます。 実際の市場とどれだけ近いかで順位が決まるというなかなかトリッキーなコンペになります。 コンペで出てくる専門用語 オーダーブック 買いと売りの価格による日本でいうところの板。 密度が高いものは頻繁にトレードされているか、動きが激しいとみなせます。 トーレド 実際に売買が行われたあとのオーダーブックとの差です。 というより、トレードによって上記オーダーブックの値が変化することになります。 日本と同じで、最低売値から買われることは同じです。 下のオーダーブックの場合、 価格 : 148、 数量 : 20 のトーレドが行われたと推測できます。 Market making and market efficiency 上の表の市場の場合流動性(効率とも呼ばれてる)は低いといえます。 というのも 価格 : 148 では買えず、待ちの状態になります。 価格 : 問わない, 数量 : 20 の注文を出した場合 149 : 1 150 : 12 151 : 7 とばらばらに購入することになり、希望通りの取引はできません。これを非効率的な市場と呼びます。 これを解決させるのが、マーケットメーカーと呼ばれる存在になります。(今回のホスト) 金融機関が流動性確保のために、こういった株に対して売買気配置を示すことが制限されています。(国からの命令) これによって一定の流動性が保たれるとされています。 オーダーブック統計 Optiverのデータサイエンティスト推奨のオーダブックから抽出できる統計値です。 bid/ask spread 最高売値と最低買値の比率をとって計算される値。 小さいと流動性が高いと見なせます。 $$BidAskSpread = BestOffer/BestBid -1$$ Weighted averaged price(wap) 日本語の加重平均価格の事です 例)100円のケーキと200円のケーキを1個ずつ買えば、平均は150円。では100円のケーキを7個と200円のケーキを3個買えば、(100円×7個)+(200円×3個)=1,300円。これを10個で割ったら130円になります。 これを先程のオーダーブックに適用したものが株価の加重平均価格です。 $$WAP = \frac{BidPrice_{1}*AskSize_{1} + AskPrice_{1}*BidSize_{1}}{BidSize_{1} + AskSize_{1}}$$ 上の例で計算を行うと bidsize = 251 asksize = 221 bidprice = 147 askprice = 148 (bidprice * asksize + askprice * bidsize) / (bidsize + asksize) # 出力 147.53177966101694 となります。 株式評価額 加重平均が同じな場合でも、株式評価額は異なります。 というのも、オファーサイズが大きい場合その市場には売り手が多く存在することになります。そうなると一般的に株の価値は上がりづらく結果として株式評価額は小さくなると推測されます。 Log return 株価の割合の比率を対数で取ったものになります。 $$r_{t_1, t_2} = \log \left( \frac{S_{t_2}}{S_{t_1}} \right)$$ $S_t $ : ある時間$t$での株価格$S$ 基本的には10分が目安となります。また - 時間をまたいで加法的である $r_{t1},r_{t2}+r_{t2},r_{t3}=r_{t1},r_{t3} $ - 通常のリターンは-100%以下にはならないが、Log returnは境界がない といった特徴があります。 また、対数関数の特徴として 価格が落ちた場合、rは少数になるのでyは-の値を取る。 価格が上がった場合、rは自然数になるのでyは+の値を取る。 もし最終的に変化がなければ、0を取る。 Realized volatility Log returnの標準偏差を1年間とみなして計算する年間標準偏差をボラティリティとよびます。 今回の目的変数です。 $$\sigma = \sqrt{\sum_{t}r_{t-1, t}^2}$$ 10分刻みでLog returnを求めて、それを一年単位で行い標準偏差を求めるとされています。 シンプルなLog returnとは違い、標準偏差になるので最終変動が0であっても10分刻みで動きが激しければボラティリティは高い値をとります。 つまり流動性が高く、いい市場になっているといえます。 データセットについて (値はダミーになります) 教師データ time_id 時間id,名前は時間には関係ないので注意 stock_id 銘柄のid target ボラティリティの値 stock_id time_id target 0 0 5 1 1 2 11 2 2 19 16 3 3 23 31 4 4 10 62 5 オーダーブックデータ time_id 時間id,名前は時間には関係ないので注意 seconds_in_bucket 秒数, 0から絶対始まる。動きがあると行が追加される。 bid_size1, bid_size2 競争力の高い買いの株式数 和訳が難しいが、現在価格に近い買い株式数の事 ask_size1, ask_size2 同様に売りの株式数 bid_price1, ask_price1, bid_price2, ask_price2 最小の買値/ 現在の価格と最小から2番目の買値/ 現在の価格 最大の売値 / 現在の価格と最大から2番目の売値 / 現在の価格 stock_id 銘柄のid wap(Weighted averaged price) 1秒単位の移動平均 log_return 上で述べたLog return値 time_id seconds_in_bucket bid_price1 ask_price1 bid_price2 ask_price2 bid_size1 ask_size1 bid_size2 ask_size2 stock_id wap log_return 1 1 6 18 18 18 129 3 10 1 100 0 1 0 2 2 7 38 1 1 1 3 20 2 100 0 14 0 3 3 8 4 18 18 1 3 30 3 100 0 13 0 4 4 7 508 18 18 0 3 40 4 100 0 13 0 5 5 9 68 18 158 10 3 50 5 100 0 14 0 トレードデータ price 1秒間に取引が成立した平均価格。 価格は取引が成立した株式数と金額の平均値で加重平均を取ったもので正規化されている size priceの価格でいくつの株式数が取引されたか order_count 取引注文の数 time_id seconds_in_bucket price size order_count stock_id 0 1 11 1 100 0 0 1 2 12 4 200 0 10 2 3 13 1 300 0 20 3 4 14 1 400 0 30 4 5 15 1 500 10 40 EDA 実際にコードがあった方がわかりやすいと思いますのでkaggleのカーネルのリンクを参照してください。 よければVoteしてくださるととてもやる気が出ます。 https://www.kaggle.com/satoshimts/optiver-volatility-introduction 最後に 特徴量作成やモデル作成については現在取り組み中... 記事にする元気が出たら記事にするかもしれないです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python(mapとlambda)

ラムダ式とMapについてここで整理しておく。 ・まず、簡単な関数で考える。 #簡単な関数(その1) def calc(a,b): #calc関数に二つの引数aとbを渡す return a*b #aとbを掛け合わせた後、返す。 calc(3,10) >>>30 ・上記の関数について、lambdaでは以下のように書き換えることができる。 #lambda関数(無名関数) (lambda a,b:a*b)(3,10) >>>30 ・もう一つ簡単な関数を用意する。 #簡単な関数(その2) def calc(x): return x*2 for num in [1,2,3,4]: print(calc(num)) >>>2 >>>4 >>>6 >>>8 ・上記の関数について、lambdaもしくはmapを用いて以下のように書き換えることができる。 #map関数 list(map(calc,[1,2,3,4])) #map関数とlambdaの組み合わせ list(map(lambda x:x*2,[1,2,3,4])) >>>[2,4,6,8] 今回は、mapとlambdaについて記事としてまとめた。 今後、pythonのテクニックについて、いろいろとまとめていきたい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python(mapとlambdaとオブジェクト化について)

ラムダ式とMapとオブジェクト化についてここで整理しておく。 ・まず、簡単な関数で考える。 #簡単な関数(その1) def calc(a,b): #calc関数に二つの引数aとbを渡す return a*b #aとbを掛け合わせた後、返す。 calc(3,10) >>>30 ・上記の関数について、lambdaでは以下のように書き換えることができる。 #lambda関数(無名関数) (lambda a,b:a*b)(3,10) >>>30 ・もう一つ簡単な関数を用意する。 #簡単な関数(その2) def calc(x): return x*2 for num in [1,2,3,4]: print(calc(num)) >>>2 >>>4 >>>6 >>>8 ・上記の関数について、lambdaもしくはmapを用いて以下のように書き換えることができる。 #map関数 list(map(calc,[1,2,3,4])) #map関数とlambdaの組み合わせ list(map(lambda x:x*2,[1,2,3,4])) >>>[2,4,6,8] ・次に、クラスとそのオブジェクト化(インスタンス化)について整理しておこうと思う。 #クラスの作成 class calc: #__init__は特殊メソッドの一つでほかの言語でコンストラクタに該当する。 #コンストラクタとはオブジェクト化と同時、初期化されることをいう #selfはあまり意識する必要はない。python特有の書き方であることを覚えておくとよい。 def __init__(self,x,y): self.x=x self.y=y #複数のメソッドを用意した。 #メソッド1 def add(self,a,b): return a+b #メソッド2 def add_another(self): return self.x+self.y #メソッド3 def mutli(self,a,b): return a*b #値を渡したうえで、オブジェクト化 a=calc(3,4) #それぞれのメソッドを呼び出す a.add_another(),a.add(2,12),a.mutli(1,9) >>>(7, 14, 9) 今回は、map,lambda,クラス・オブジェクト化について記事としてまとめた。 今後、pythonのテクニックについて、いろいろとまとめていきたい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RFAの記録をネットでする。(Twitterだけでなく)

RFA→Twitter→Simplenote(→Scrapbox) 初めに 日々リングフィットアドベンチャー(RFA)をやっていまして、その結果をRFAやSwitchだけに留めとくだけでは記録としてはもったいないので、ネットに上げたいと思いました。ただSwitchから直接アップロード出来るのはTwitterぐらい。(フェイスブックもあるけど笑) Twitterだと垂れ流しには便利だけと記録には向いてないので、記録に向いているサービス、例えばSimplenoteやScrapboxにちゃんとタグとかリンクを付けて上げていくようにしたいと考えました。 ロジック RFA→Switch: プレイ後の記録のスクリーンショットをSwitchの機能で撮る。手動。 Switch→Twitter: ここはSwitchの機能でTwitterに上げる。手動。 Twitter→Simplenote: ここが今回のメイン部分。自動。 Simplenote→Scrapbox: ここも自動化したかった。コピペ手動。 というかTwitterからScrapboxに直接処理させたかったけど、Scrapboxのプログラム用APIが存在しないみたいで無理みたい。なのでSimplenoteからコピペしやすいように上のプログラムで整形させる。 メイン部分のPythonプログラム まずは結論から。これを実行すると対象のユーザーの直近のツイート郡からハッシュタグや画像が載ってる実行当日のツイートから画像のURLをコピーして整頓してSimplenoteに追加する。 TwitterからSimplenoteに画像URLをコピーする # -*- coding: utf-8 -*- from configparser import ConfigParser import urllib3 import json from datetime import datetime, timezone import time import pytz import simplenote # TwitterAPIを使うための認証用トークンを読み込む config = ConfigParser() config.read('config.ini') TW = 'Twitter' BT = 'bearer_token' USER = 'user_name' bearer_token = config.get(TW, BT) user_name = config.get(TW, USER) http = urllib3.PoolManager() # Twitterから検索して必要な情報を読み取る def call_api(url:str, search_field:dict={}) -> dict: """ param url : エンドポイントURL param search_field : 検索用パラメータ return : レスポンス内容 """ headers = {'Authorization': 'Bearer '+bearer_token} res = http.request(method='GET', url=url, headers=headers, fields=search_field) if res.status != 200: raise urllib3.exceptions.HTTPError(res.status) return json.loads(res.data) def change_timezone_day(created_at:str) -> str: """ created_at :TwitterAPIから取得した日時 :タイムゾーンが日本とは異なるため補正する return :補正後の日にち """ st = time.strptime(created_at, '%Y-%m-%dT%H:%M:%S.000Z') utc_daytime = datetime(st.tm_year, st.tm_mon, st.tm_mday, st.tm_hour, st.tm_min, st.tm_sec, tzinfo=timezone.utc) jst_daytime = utc_daytime.astimezone(pytz.timezone('Asia/Tokyo')) return_day = datetime.date(jst_daytime) return str(return_day) # 必要なツイートを取得する。自分のアカウントのハッシュタグと画像が含まれている直近のツイートを探す search_url = r'https://api.twitter.com/2/tweets/search/recent' query = 'from:{user_name} #リングフィットアドベンチャー #RingFitAdventure #NintendoSwitch has:images'.format(user_name=user_name) params = { 'query': query, 'expansions': 'attachments.media_keys', 'tweet.fields' : 'created_at', 'media.fields' : 'url', } result = call_api(url=search_url, search_field=params) # 不要な日にちのツイートも含まれている可能性があるので、必要な日にち(基本今日)だけを取り出す # その対象のツイートのmedia_keyだけ取り出す today = datetime.date(datetime.today()) for tw_data in result['data']: created_at = change_timezone_day(tw_data['created_at']) if created_at == str(today): medias = tw_data['attachments']['media_keys'] break # media_keyから画像のURLを取り出す setting_url = [] if 'medias' in locals(): tweet_media_list = result['includes']['media'] for media_key in medias: for item_media in tweet_media_list: if item_media['media_key'] == media_key: setting_url.append(item_media['url']) break if len(setting_url) != 0: SN = 'Simplenote' SN_USER = 'user_name' SN_PASS = 'password' user = config.get(SN, SN_USER) password = config.get(SN, SN_PASS) sn = simplenote.Simplenote(user, password) str_today = today.strftime('%Y/%m/%d') sn_title = str_today + 'のRFA¥n' link_day = '[{day}]¥n'.format(day=str_today) link_RFA = '[リングフィット アドベンチャー]¥n' tags = '#任天堂¥n#NintendoSwitch¥n#ゲーム¥n#日記¥n¥n' note = """{day}のRFA [{day}] [リングフィット アドベンチャー] #任天堂 #NintendoSwitch #ゲーム #日記 """.format(day=str_today) for su in setting_url: note += """[{url}] """.format(url=su) sn.add_note(note=note) 個別のロジックの説明 1.Twitterの認証 ConfigParserを使ってiniファイルを読み込んで認証用のbearerトークンとTwitterユーザーを読み込むようにする。 ConfigParserを使う # TwitterAPIを使うための認証用トークンを読み込む config = ConfigParser() config.read('config.ini') TW = 'Twitter' BT = 'bearer_token' USER = 'user_name' bearer_token = config.get(TW, BT) user_name = config.get(TW, USER) 2.Twitterから検索する http = urllib3.PoolManager() # Twitterから検索して必要な情報を読み取る def call_api(url:str, search_field:dict={}) -> dict: """ param url : エンドポイントURL param search_field : 検索用パラメータ return : レスポンス内容 """ headers = {'Authorization': 'Bearer '+bearer_token} res = http.request(method='GET', url=url, headers=headers, fields=search_field) if res.status != 200: raise urllib3.exceptions.HTTPError(res.status) return json.loads(res.data) 3.Twitterから実際に必要な情報を取得する ユーザー名とタグを指定して必要なつぶやきだけ取得する。 # 必要なツイートを取得する。自分のアカウントのハッシュタグと画像が含まれている直近のツイートを探す search_url = r'https://api.twitter.com/2/tweets/search/recent' query = 'from:{user_name} #リングフィットアドベンチャー #RingFitAdventure #NintendoSwitch has:images'.format(user_name=user_name) params = { 'query': query, 'expansions': 'attachments.media_keys', 'tweet.fields' : 'created_at', 'media.fields' : 'url', } result = call_api(url=search_url, search_field=params) 4.Twitterから取得した情報の日時を日本時間に修正する 取得した情報のタイムゾーンはUTCみたいなので、JSTに直す。 def change_timezone_day(created_at:str) -> str: """ created_at :TwitterAPIから取得した日時 :タイムゾーンが日本とは異なるため補正する return :補正後の日にち """ st = time.strptime(created_at, '%Y-%m-%dT%H:%M:%S.000Z') utc_daytime = datetime(st.tm_year, st.tm_mon, st.tm_mday, st.tm_hour, st.tm_min, st.tm_sec, tzinfo=timezone.utc) jst_daytime = utc_daytime.astimezone(pytz.timezone('Asia/Tokyo')) return_day = datetime.date(jst_daytime) return str(return_day) 5.必要な情報だけ抜き出す 必要な日にち(基本実行当日)のRFAの結果画像が載っているつぶやきの画像URLだけ取得する。 # 不要な日にちのツイートも含まれている可能性があるので、必要な日にち(基本今日)だけを取り出す # その対象のツイートのmedia_keyだけ取り出す today = datetime.date(datetime.today()) for tw_data in result['data']: created_at = change_timezone_day(tw_data['created_at']) if created_at == str(today): medias = tw_data['attachments']['media_keys'] break # media_keyから画像のURLを取り出す setting_url = [] if 'medias' in locals(): tweet_media_list = result['includes']['media'] for media_key in medias: for item_media in tweet_media_list: if item_media['media_key'] == media_key: setting_url.append(item_media['url']) break 6.Simplenoteに書き出す if len(setting_url) != 0: SN = 'Simplenote' SN_USER = 'user_name' SN_PASS = 'password' user = config.get(SN, SN_USER) password = config.get(SN, SN_PASS) sn = simplenote.Simplenote(user, password) str_today = today.strftime('%Y/%m/%d') sn_title = str_today + 'のRFA¥n' link_day = '[{day}]¥n'.format(day=str_today) link_RFA = '[リングフィット アドベンチャー]¥n' tags = '#任天堂¥n#NintendoSwitch¥n#ゲーム¥n#日記¥n¥n' note = """{day}のRFA [{day}] [リングフィット アドベンチャー] #任天堂 #NintendoSwitch #ゲーム #日記 """.format(day=str_today) for su in setting_url: note += """[{url}] """.format(url=su) sn.add_note(note=note)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DjangoーCBVのソースコード分析してみる。

 Views層でFBVとCBVを書く時、なぜ同じ結果が得られるかの疑問はないでしょうか。そしてUrls層でルーティングを設定する場合もCBVとFBVの書き方が変わりますよね? その原因をソースコードに合わせ、見ていきたいと思っています。  CBVの根本的なところに入るための入口はどこにあるか、そしてどの流れでgetやpostを実行するのかを見てみましょう! 入口 path('books1/', views.Books.as_view()) as_view()を入り口とし、後ろのソースコードを追跡します。 はい、では、@classonlymethodはviews.Books.as_view()と書く理由で、クラスメソッドのことです。 as_viewメソッドはviewが戻り値になり、このviewは実際にas_view内部の関数のことを指しています。 view関数の戻り値はdispatch関数なので、次はdispatchを追跡します。 ここで、ちょっと補足しますが、pythonの継承関係について。このdispatchの例で言うと、dispatchを実行したい場合、最初はクラスのobject(インスタンス)から探します、そしてobjectが所属したclass、って継承されたclassの流れでdispatchを探します。今回はobjectにdispatch方法がないため、自然にViewクラスのdispatch方法を実行します。* dispatch def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, # defer to the error handler. Also defer to the error handler if the # request method isn't on the approved list. if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) これはViewクラスのdispatch方法です。引数について、selfはobjectのこと、requestはurlsで与えられたrequestのことです。 if文のところから見てみます。request.method.lower()は例えばPOSTやGETを小文字化するため、self.http_method_namesはなんやろ?? 実はViewクラスで定義され、 http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] となります。 次に、if分が成立したら、ようするにrequest methodがこのリストに入っているのであれば、次を実行します。 handler = getattr(self, request.method.lower(), self.http_method_not_allowed) getattrを使って、self(objectのこと)の中に、POSTやGETを小文字化した方法はあるかどうか。あるの場合はhandler変数に与え、なかった場合はself.http_method_not_allowedがhanlder変数に与えます(self.http_method_not_allowedはデフォルト値と考えてもいいだと思います))。 そしてdispatch方法に戻り、戻り値をチェックしてください。 return handler(request, *args, **kwargs) なんと!思った以上より分かりやすくて、単純にhandlerがreturnされただけ! まとめると、as_viewから入り、dispatch方法を実行し、帰ってくるのはgetやpost方法になります。 まとめ  CBVは非常に重要です、特にDjango RestFrameWork上に大きいな役割を果たしています。また、DRFは実際、DjangoのViewを継承されていますので、DRFの理解を深まるためにはCBVの実行の流れも理解する必要があるだと思っています。  それほど詳しい説明ではないですが、最後まで見ていただきありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

系統解析ツール「IQ-TREE」を利用した祖先配列推定 (Ancestral Sequence Reconstruction)

概要 祖先配列推定(ASR:Ancestral Sequence Reconstruction)は、共通祖先に由来する各生物のホモログ遺伝子により祖先遺伝子配列を推定する分子進化学における手法を示す。祖先配列推定により、遺伝子(タンパク質)の進化のメカニズムやダイナミクスが解明されてきた。 本稿では、系等解析ツールの一つである「IQ-TREE」を利用した祖先配列推定の実行手順及び自動化Pythonスクリプトを記載する。 ※ IQ-TREEのv2.x系にて動作を確認したものであり、v1.x系では動作しません 実行手順・結果 IQ-TREEを利用した祖先配列推定における、「入力データ」・「実行コマンド」・「出力結果データ」について記載する。 ※ IQ-TREE(v2.x系)がインストール済であること (IQ-TREE公式サイト) 1. 入力データ 系統樹ファイル 真猿型下目(Simiiformes)の種の系統樹(newick形式)をサンプルとして利用 内部ノード識別子を与えておくことで、後のデータ解釈・処理が楽になるため、 図に示すように内部ノードへ'N000,N001...N0XX'の連番IDを付与 simiiformes.nwk ((((Saimiri_boliviensis,Cebus_capucinus)N003,Callithrix_jacchus)N002,Aotus_nancymaae)N001,((((((Pan_paniscus,Pan_troglodytes)N009,Homo_sapiens)N008,Gorilla_gorilla)N007,Pongo_abelii)N006,Nomascus_leucogenys)N005,((Rhinopithecus_roxellana,Rhinopithecus_bieti)N011,(Chlorocebus_sabaeus,(((Macaca_mulatta,Macaca_fascicularis)N015,Macaca_nemestrina)N014,(Papio_anubis,(Cercocebus_atys,Mandrillus_leucophaeus)N017)N016)N013)N012)N010)N004)N000; アライメント済のCDS遺伝子配列ファイル 系統樹に対応する祖先配列推定対象の各生物CDS遺伝子配列における アライメント済FASTAファイルをサンプルとして利用 「系統樹内の各生物名」と「配列アノテーション」の総数及び名称は必ず一致している必要がある。 cds_align.fasta >Rhinopithecus_bieti MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDVLLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLKSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPTPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQIS-----PFSSIFPKCFFSGSMPINSKKHIQRDYYYTLLQTGDPFSQSIKFPINGLSDIKNTLEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLATNVNPGDGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQITPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLVLPELRTE--MVPKKDEVSSVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Aotus_nancymaae MGSENSALKSYTLKEPAFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVPQATPEFLRSIQSVRDPASIPPEEMSPEFTTLPECHGHARDAFSFGILVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-GHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPVRVVCSQHSQISPILENPFSSIFPKCFFSGNMPIN-KKHIHQDYYNTLLQTGNPFSQPIKFPINGLSDVKNSSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQVWPREPCDAVKSQCTTLDVGE-SSWDDCEPGSLDTKVNPEGGITATKPVTSGKQKPIPALLPLTEES-TTWKSSLPQKTSLLQSGDDPDQIKPPKVSSQEKPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPNKDDVSPVMQFSSKFAAAEVAEGEAEGW-EEGELNWE--DNNW >Callithrix_jacchus MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALDTLSSAEVCAGIYDILLALTFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSVRDPASIPPEEMSPEFTTLPECDGHARDAFSFGILVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPVRVVCSQHSQISPILENPFSSIFPKCFFSGNMPIN-KKHIQQDYYNTLLQTGNPFSQPIKFPINGLSDVKNSSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-LSWDDCEPGSLDTKVNLGAGITATKPVTSGKQKPIPALLPLTEES-TTWQSRLSQKTSLVQSRDDPDQIKPPKVSSQERPLKISSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVSNKDDVSPVMQFSSKFAAAEIAEGEAEGW-EEGELNWE--DNNW >Macaca_mulatta MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLLDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWHREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLP------QNGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEICPMMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Cebus_capucinus MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALTFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSVRDPASIPPEEMSPEFTALPECHGHARDAFSFGILVESLLTILNKQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPVRVVCSQHSQISPILENPFSSIFPKCFFSGNMPIN-KKHIQQDYYNTLLQTGDPFSQPIKFPISGLPDVKNSSEDSENFPSSSKKS-EDWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDVEE-SSWDDCEPGSLDTKVNPGGGITATKPVTSGEQKPIPALLPFTEES-TTWKSSVPGKTGLVQSRDDPDQIKSPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPNKDDVSPVMQFSSKFAAAEITEGEAEGW-EEGELNWE--DNNW >Saimiri_boliviensis MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVAQATPEFLRSIQSVRDPASIPPEEMSPEFTTLPECHGHARDAFSFGILVESLLTILNKQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHV-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPVRVVCSQRSQISPILENPFSSIFPKCFFSGNMPIN-KKHIQQDYYNTLLQTGDPFSQPIKFPINGLSDIKNSSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDVEE-SSWDDCEPGSLNTKVNPGGGITATKPVTSGEQKLIPALLPFTEES-TTWKSSLPQKTSLVQSRDDPDHIKPPKVSSQERPLKVPSELGLGEEFTIQVRKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPNKDDVSPVMQFSSKFAAAAITEGEAEGW-EEGELNWE--DSNW >Cercocebus_atys MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPGLFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Mandrillus_leucophaeus MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK----------------------------------------------------------------VLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNSLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTLGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Chlorocebus_sabaeus MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFRSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Papio_anubis MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLS-------------------------------------------------------------QPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Macaca_fascicularis MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWHREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSMEQKPIPALLPLTEES-MPWKSSLPQKTSLVQNGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEICPMMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Macaca_nemestrina MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWHREPCDAVKSQCTTLDMEE-SSWDDCEPSNLATKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQNGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEICPMMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Rhinopithecus_roxellana MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLKSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYYTLLQTGDPFSQSIKFPINGLSDIKNTLEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLATNVNPGDGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQITPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLVLPELRTE--MVPKKDEVSSVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Gorilla_gorilla MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPYLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQDQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPELVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQISPILENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDDVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLSLTEES-MPWKSSLPQKTSLVQRGDDADQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Pan_troglodytes MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEVDGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPYLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQISPILENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPRETCDDVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLSLTEES-MPWKSSLPQKTSLVQRGDDADQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Homo_sapiens MGSENSALKSYTLREPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPYLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNTDLSLEDSPMCVVCSHHSQISPILENPFSSIFPKCFFSGSTPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDDVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLSLTEES-MPWKSSLPQKISLVQRGDDADQIEPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Pan_paniscus MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEVDGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFF---------------------------FLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPYLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQISPILENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENKTVNIQIWPRETCDDVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLSLTEES-MPWKSSLPQKTSLVQRGDDADQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Nomascus_leucogenys MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQILPILENPFSSIFPKCFFSGSMPINSKKHIQQDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCNTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSFVQRGNDADQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >Pongo_abelii MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQILPILENPFSSIFPKCFFSGSMPINSKKHIQQDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQRGDDPDQIKLPKVSSQGRPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW 2. IQ-TREE実行コマンド 前述の入力データを利用した祖先配列推定を下記コマンドにより実行可能 iqtree --ancestral -s cds_align.fasta -te simiiformes.nwk -m LG+I+G4 -asr-min 0.95 --prefix iqtree_asr -T 4 --seed 0 --redo 利用コマンドオプション オプション 内容 --ancestral 実行モード = 祖先配列推定 -s 入力アライメントファイル -te 入力系統樹ファイル -m 置換モデル (指定なしの場合、自動で最適な置換モデルを決定) -asr-min 祖先配列推定時の確率閾値 (閾値を満たさない場合、gapで穴埋め) --prefix 出力ファイルのPrefix -T データ処理時のCPU利用数 --seed 乱数シード (再現性が必要な場合に指定) --redo 前回結果が存在する場合でも上書き ※ コマンドオプション詳細はiqtree --helpで確認 3. 出力結果データ IQ-TREEによる祖先配列推定結果が「iqtree_asr.state」ファイルに下記のように出力される。 各系統樹ノード(Node列)の各座位位置(Site列)に対応する推定祖先アミノ酸(State列)が一行毎に記載される。 -asr-minオプションに指定した閾値以上の事後確率をもつアミノ酸が推定祖先アミノ酸(State列)となっている。 iqtree_asr.state Node Site State p_A p_R p_N p_D p_C p_Q p_E p_G p_H p_I p_L p_K p_M p_F p_P p_S p_T p_W p_Y p_V N015 1 M 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 1.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 N015 2 G 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 1.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 N015 3 S 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 1.00000 0.00000 0.00000 0.00000 0.00000 〜〜〜(省略)〜〜〜 N011 750 N 0.00000 0.00000 1.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 N011 751 N 0.00000 0.00000 1.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 N011 752 W 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 1.00000 0.00000 0.00000 上記より系統樹ノード(Node列)に紐づく推定祖先アミノ酸(State列)を抽出することで、 下記に示す各系統樹ノードにおける推定祖先配列を取得できる。 iqtree_asr.fasta >N001 MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSVRDPASIPPEEMSPEFTTLPECHGHARDAFSFGILVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPVRVVCSQHSQISPILENPFSSIFPKCFFSGNMPINSKKHIQQDYYNTLLQTG-PFSQPIKFPINGLSDVKNSSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDVEE-SSWDDCEPGSLDTKVNPGGGITATKPVTSG-QKPIPALLPLTEES-TTWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPNKDDVSPVMQFSSKFAAAEI-EGEAEGWEEEGELNWE--DNNW >N002 MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLAL-FLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSVRDPASIPPEEMSPEFTTLPECHGHARDAFSFGILVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPVRVVCSQHSQISPILENPFSSIFPKCFFSGNMPINSKKHIQQDYYNTLLQTG-PFSQPIKFPINGLSDVKNSSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDVEE-SSWDDCEPGSLDTKVNPGGGITATKPVTSG-QKPIPALLPLTEES-TTWKSSLPQKTSLVQSRDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPNKDDVSPVMQFSSKFAAAEI-EGEAEGWEEEGELNWE--DNNW >N003 MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLAL-FLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSVRDPASIPPEEMSPEFTTLPECHGHARDAFSFGILVESLLTILNKQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPVRVVCSQHSQISPILENPFSSIFPKCFFSGNMPIN-KKHIQQDYYNTLLQTGDPFSQPIKFPINGLSDVKNSSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDVEE-SSWDDCEPGSLDTKVNPGGGITATKPVTSGEQKPIPALLPFTEES-TTWKSSLPQKTSLVQSRDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPNKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N004 MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCS-HSQISPILENPFSSIFPKCFFSGSMPINSKKHIQQDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N005 MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQI-PILENPFSSIFPKCFFSGSMPINSKKHIQQDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQRGDD-DQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N006 MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQI-PILENPFSSIFPKCFFSGSMPINSKKHIQQDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQRGDD-DQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N007 MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPYLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQISPILENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDDVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLSLTEES-MPWKSSLPQKTSLVQRGDDADQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N008 MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPYLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQISPILENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDDVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLSLTEES-MPWKSSLPQKTSLVQRGDDADQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N009 MGSENSALKSYTLKEPPFTLPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEVDGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGHLTHNNVCLSSVFVSEDGHWKLGGMETVCKVSQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPKCRPALCTLLSHDFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPYLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSPMRVVCSHHSQISPILENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTSEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPRETCDDVKSQCTTLDVEE-SSWDDCEPSSLDTKVNPGGGITATKPVTSGEQKPIPALLSLTEES-MPWKSSLPQKTSLVQRGDDADQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDDVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N010 MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDS-NFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N011 MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLKSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYYTLLQTGDPFSQSIKFPINGLSDIKNTLEDSENFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLATNVNPGDGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQITPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLVLPELRTE--MVPKKDEVSSVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N012 MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N013 MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N014 MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWHREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQNGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEICPMMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N015 MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWHREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQNGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEICPMMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N016 MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW >N017 MGSENSALKSYTLKEPPFILPSGLAVYPAVLQDGKFASVFVYKRENEDKVNKAAKHLKTLRHPCLLRFLSCTVEADGIHLVTERVQPLEVALETLSSAEVCAGIYDILLALIFLHDRGQLTHNNVCLSSVFVSEDGHWKLGAMETVCKISQATPEFLRSIQSIRDPASIPPEEMSPEFTTLPECHGHARDAFSFGTLVESLLTILNEQVSADVLSSFQQTLHSTLLNPIPNCRPALCTLLSHEFFRNDFLEVVNFLKSLTLKSEEEKTEFFKFLLDRVSCLSEELIASRLVPLLLNQLVFAEPVAVKSFLPHLLGPKK-DHA-QGETPCLLSPALFQSRVIPVLLQLFEVHEEHVRMVLLSHIEAYVEHFTQEQLKKVILPQVLLGLRDTSDSIVAITLHSLAVLVSLLGPEVVVGGERTKIFKRTAPSFTKNIDLSLEDSSMRVVCSKHSQISPVLENPFSSIFPKCFFSGSMPINSKKHIQRDYYNTLLQTGDPFSQPIKFPINGLSDVKNTLEDSKNFPSSSKKS-EEWPDWSEPEEP-ENQTVNIQIWPREPCDAVKSQCTTLDMEE-SSWDDCEPSNLDTKVNPGGGITATKSVTSGEQKPIPALLPLTEES-MPWKSSLPQKTSLVQSGDDPDQIKPPKVSSQERPLKVPSELGLGEEFTIQVKKKPVKDPEMDWFADMIPEIKPSAAFLILPELRTE--MVPKKDEVSPVMQFSSKFAAAEITEGEAEGWEEEGELNWE--DNNW 祖先配列推定自動化スクリプト 一連の祖先配列推定を自動で実行可能なPythonスクリプトを作成してみた。 Biopythonを利用しているので、事前にインストールが必要 (pip install biopython) 下記コマンドにより、① 系統樹内部ノードへの識別ID付与、② IQ-TREEによる祖先配列推定、③ 推定結果からの祖先配列情報の抽出、まで実行される。 「auto_asr_script.py」実行コマンド # 引数1:Newick形式の系統樹、引数2:アライメント済CDS配列FASTAファイル、引数3:出力ディレクトリ python auto_asr_script.py simiiformes.nwk cds_align.fasta output auto_asr_script.py import csv import subprocess as sp import sys from collections import defaultdict from pathlib import Path from Bio import Phylo def main(nwk_tree_file: Path, fasta_aln_file: Path, outdir: Path): """Ancestral sequence reconstruction automated script Args: nwk_tree_file (Path): Newick format tree file path fasta_aln_file (Path): Fasta format alignment file path outdir (Path): Output directory """ outdir.mkdir(exist_ok=True) # Add node id to tree nwk_nodeid_tree_file = outdir / "user_tree.nwk" add_serial_node_id(nwk_tree_file, nwk_nodeid_tree_file) # Ancestral sequence reconstruction using iqtree prefix = outdir / "iqtree_asr" iqtree_asr_cmd = f"iqtree --ancestral -s {fasta_aln_file} -te {nwk_nodeid_tree_file} -m LG+I+G4 -asr-min 0.95 --prefix {prefix} -T 4 --seed 0 --redo" sp.run(iqtree_asr_cmd, shell=True) # Write asr fasta file from iqtree state file asr_state_file = prefix.as_posix() + ".state" asr_fasta_file = prefix.as_posix() + ".fasta" write_asr_fasta_file(asr_state_file, asr_fasta_file) def add_serial_node_id(nwk_tree_infile: str, nwk_tree_outfile: str) -> None: """Add serial node id(N001, N002...N00X) in each internal tree node Args: nwk_tree_infile (str): Input newick file path nwk_tree_outfile (str): Output newick file path """ tree = Phylo.read(nwk_tree_infile, "newick") for cnt, node in enumerate(tree.get_nonterminals()): node.name = f"N{cnt:03d}" Phylo.write(tree, nwk_tree_outfile, "newick", plain=True) def write_asr_fasta_file(asr_state_infile: str, asr_fasta_outfile: str) -> None: """Write asr fasta file from iqtree asr state file Args: asr_state_infile (str): asr state file path asr_fasta_outfile (str): asr fasta file path """ node_name2asr_seq = defaultdict(str) with open(asr_state_infile) as f: reader = csv.reader(f, delimiter="\t") for row in reader: # Skip header row if row[0].startswith("#") or row[0].startswith("Node"): continue # Record node_name & asr_seq node_name, aa_pos, asr_aa, prob_list = row[0], row[1], row[2], row[3:] node_name2asr_seq[node_name] += asr_aa with open(asr_fasta_outfile, "w") as f: for node_name, asr_seq in sorted(node_name2asr_seq.items()): f.write(f">{node_name}\n{asr_seq}\n") if __name__ == "__main__": args = sys.argv nwk_tree_file, fasta_aln_file, outdir = Path(args[1]), Path(args[2]), Path(args[3]) main(nwk_tree_file, fasta_aln_file, outdir) 参考 IQ-TREE Command Reference Ancestral Sequence Reconstruction - Wikipedia その他の祖先配列推定CLIツール(他にも色々あるっぽい) FastML Source Code raxml-ng - GitHub MEGA - Molecular Evolutionary Genetics Analysis
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

pythonで移動平均計算するならbottleneckモジュールを使うべし

時系列データ(株価データ)のある値(終値)の移動平均を計算するのに、どのやり方が早いのかやってみた。 pandas numpy bottleneck(中身はnumpyが使われているらしい) PCスペック ryzen3600 結論. bottleneckでやるのが早い import pandas as pd import numpy as np import bottleneck as bn # 読み込み path = 'データ.csv' df = pd.read_csv(path) # 終値 close = df['Close'] # pandas %time ma_close = close.rolling(25).mean() # numpy def moving_average(a, n) : ret = np.cumsum(a, dtype=float) ret[n:] = ret[n:] - ret[:-n] return ret[n - 1:] / n %time ma_close = moving_average(close.to_numpy(), 25) # bottleneck def rollavg_bottlneck(a,n): return bn.move_mean(a, window=n,min_count = None) %time ma_close = rollavg_bottlneck(close.to_numpy(), 25) %time CPU times: user 332 µs, sys: 0 ns, total: 332 µs Wall time: 280 µs CPU times: user 130 µs, sys: 0 ns, total: 130 µs Wall time: 100 µs CPU times: user 42 µs, sys: 0 ns, total: 42 µs Wall time: 45.5 µs %timeit 145 µs ± 1.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 14 µs ± 86.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 4.29 µs ± 64.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

pythonで移動平均計算するならtaライブラリを使うべし

時系列データ(株価データ)のある値(終値)の移動平均を計算するのに、どのやり方が早いのかやってみた。 pandas numpy bottleneck(中身はnumpyが使われているらしい) ta PCスペック ryzen3600 結論. taでやるのが早い import pandas as pd import numpy as np import bottleneck as bn # 読み込み path = 'データ.csv' df = pd.read_csv(path) # 終値 close = df['Close'] # pandas %time ma_close = close.rolling(25).mean() # numpy def moving_average(a, n) : ret = np.cumsum(a, dtype=float) ret[n:] = ret[n:] - ret[:-n] return ret[n - 1:] / n %time ma_close = moving_average(close.to_numpy(), 25) # bottleneck def rollavg_bottlneck(a,n): return bn.move_mean(a, window=n,min_count = None) %time ma_close = rollavg_bottlneck(close.to_numpy(), 25) # ta %time ma_close = ta.trend.SMAIndicator(close,window=25 %time CPU times: user 332 µs, sys: 0 ns, total: 332 µs Wall time: 280 µs CPU times: user 130 µs, sys: 0 ns, total: 130 µs Wall time: 100 µs CPU times: user 42 µs, sys: 0 ns, total: 42 µs Wall time: 45.5 µs CPU times: user 4 µs, sys: 2 µs, total: 6 µs Wall time: 6.91 µs taライブラリの詳細↓ https://technical-analysis-library-in-python.readthedocs.io/en/latest/index.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

pythonで移動平均計算するならbottleneckライブラリを使うべし

時系列データ(株価データ)のある値(終値)の移動平均を計算するのに、どのやり方が早いのかやってみた。 pandas numpy bottleneck(中身はnumpyが使われているらしい) PCスペック ryzen3600 結論. bottleneck import pandas as pd import numpy as np import bottleneck as bn # 読み込み path = 'データ.csv' df = pd.read_csv(path) # 終値 close = df['Close'] # pandas %time ma_close = close.rolling(25).mean() # numpy def moving_average(a, n) : ret = np.cumsum(a, dtype=float) ret[n:] = ret[n:] - ret[:-n] return ret[n - 1:] / n %time ma_close = moving_average(close.to_numpy(), 25) # bottleneck def rollavg_bottlneck(a,n): return bn.move_mean(a, window=n,min_count = None) %time ma_close = rollavg_bottlneck(close.to_numpy(), 25) %time CPU times: user 332 µs, sys: 0 ns, total: 332 µs Wall time: 280 µs CPU times: user 130 µs, sys: 0 ns, total: 130 µs Wall time: 100 µs CPU times: user 42 µs, sys: 0 ns, total: 42 µs Wall time: 45.5 µs
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

テスト記事

python 簡単な実装まとめ test.py def add(a,b): #簡単な足し合わせ演算 aとbを引数として渡す return a+b #足し合わせた結果を返す result=add(3,5) print(result) >>>8 -関数については、引数と返り値がキーワードとなる。 まだ、テスト段階である。今後、より内容を充実させていこうと思う。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Mediapipeを使ってじゃんけんしてみた

環境 Jupyter Notebook(6.1.4)を用いて作業を進めました。 主要なライブラリのバーションは以下の通りです。 OpenCV(4.5.3), Tensorflow(2.5.0) また、ディレクトリの構成は後述します。 きっかけ 推しとじゃんけんがしたい 今までMediaPipeを使って手の検出をしたり、OpenCVを使って俺の愛馬を検出したりしてきました。少しずつ操作になれてきたので、今まで使った技術を使って何かやってみたいと考えました。手の形状を使うゲームとしてぱっと思い浮かんだのがじゃんけんだったので、「パソコンのカメラに手を出してじゃんけんをする」という動作に挑戦してみました。 概要 目指す形としては、音声の合図でPCのカメラに手を出して形を認識してもらい、勝負の結果を表示する(BGM付)、というものです。 作業工程は以下の通りです。 素材を集める(手、表示する画像、再生する音声) MediaPipeを使って手の写真から検出ポイントの座標を集める 検出ポイントの座標からじゃんけんの手を予測するモデルを作る じゃんけんする 今までの経験のおかげで3番目まではすんなりと行うことができました。最後の4番目については、音声の再生など私にとって初めて取り扱うことも多かったのでちょっと苦戦しましたが、おかげで得られたものも多かったので取り組んでよかったです。 一番の苦労は作業開始前ごはんを作るときにピーラーで右手薬指のさきっぽの皮をそぎ落としたことでした。絶妙に絆創膏が張りずらい場所のため、絆創膏を外したら血濡れのキーボードが出来上がるし、絆創膏をしたらしたでキーボード打つときに変な感じがするし散々でした。指先は大切にするよう心掛けていきたいと思いました。 というわけで以下にやったことの詳細と反省点をまとめておきたいと思いますのでお付き合いください。 ①素材を集める 作業のため、以下のようなディレクトリ構成を作りました。 file/ ├─ notebook.ipynp <- コードはすべてここで実行 ├─ landmarkdata.csv <- 後で作成する検出ポイントの座標が入ったファイル ├─ item/ │ ├─ startimage.jpg │ ├─ win.png │ ├─ drow.png │ ├─ lose.png │ └─ sorry.png ├─ voice/ │ ├─ jankenpon.wav │ ├─ win.wav │ ├─ drow.wav │ └─ lose.wav ├─ model/ │ └─ あとで予測モデルを保存 └─ hand/ ├─ choki/ ├─ gu/ └─ pa/ まずはモデル作成のための手の画像を集めます。自分のスマホの連写機能を使い、グーチョキパー各200枚ずつ用意しました。指先の認識を阻害しないため絆創膏は外しました。撮った写真はそれぞれの手の名前をつけたフォルダに保存しておきます。 また、ゲーム中に使いたい画像や音声(スタート時、勝ち、あいこ、負け、エラーの5パターン)を集めてそれぞれitemフォルダやvoiceフォルダに保存しておきます。 今回音声については「じゃんけん フリー音声」や「フリー 効果音 勝利」などで検索してよさげなものをmp3ファイルでダウンロードさせていただき、変換サイトを使ってwavファイルに変換させていただきました。無料で使えるものがたくさんあってありがたい世の中です。 また画像についてはペイントを使って適当に用意しました。itemフォルダの中は下のような感じです。 自分の手とPCの手を表示したかったので結果画面で使いたいものについては真ん中をあけておきました。なおこの素材集めの部分に推しとじゃんけんするための可能性が秘められているのでこのあと差し替えて推しとじゃんけんできるようにしました ②MediaPipeを使って手の写真から検出ポイントの座標を集める 次に集めた手の画像を使って座標の検出ポイントを集めていきます。この作業は以前以下の記事でやったこととほとんど同じなのでさくさく進みました。 前記事のおさらいになりますが、公式ガイドによれば下の画像の全21か所の座標を検出することができ、得られる座標は画像サイズによって正規化されています。 まずは各ファイルのパスとラベルをしまった表を作ります。 #必要なライブラリをインポート import os import glob import cv2 import pandas as pd import mediapipe as mp df = [] for foldername in os.listdir('./hand/'): imgs_path = './hand/' + foldername imgs = sorted(glob.glob(imgs_path + '/' + '*.jpg')) for name in imgs: df.append((str(name), str(foldername))) df = pd.DataFrame(df, columns=['img', 'label']) df.head() 次に、各画像を読み込んで手の検出ポイントの座標を取得していきます。 #検出器のインスタンス化 hands = mp.solutions.hands.Hands( static_image_mode=True, #静止画モード max_num_hands=1, #検出する手の数(じゃんけんは片手の想定なので1に) min_detection_confidence=0.5) df1 = [] for idx, file in enumerate(df['img']): print('No', idx) #画像を読み込んで左右反転させる image = cv2.flip(cv2.imread(file), 1) #色をRGBにして手の検出を行う results = hands.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) #手が検出されなければ次の画像へ if not results.multi_hand_landmarks: print('No Hand') print('-------------------------') continue mark_list = [] #21個の検出ポイントを取得 for i in range(21): x = results.multi_hand_landmarks[0].landmark[i].x y = results.multi_hand_landmarks[0].landmark[i].y z = results.multi_hand_landmarks[0].landmark[i].z mark_list.append(x) mark_list.append(y) mark_list.append(z) #手のラベルと合わせてdf1に保存 mark_list.append(df['label'][idx]) df1.append(mark_list) print(complete) print('-------------------------') df1 = pd.DataFrame(df1) df1.shape #---> (597, 64) カラムは21検出ポイント×(x, y, z)の63にラベルを足した64個出来上がっています。用意した画像のうち3枚くらいはうまく検出できなかったみたいです。 このあたりで指先の傷口が開いたのに気づかずキーボードのLとOのあたりが血まみれになったので消毒作業が入りました。 気を取り直し、今回は左手か右手かが重要ではないので、モデルのためのデータの水増しの手段として上と同じことを反転なしで行い、concatを使って結合しました。 df2 = [] for idx, file in enumerate(df['img']): print('No', idx) image = cv2.imread(file, 1) #flipしない→逆の手としてデータとれるはず results = hands.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) if not results.multi_hand_landmarks: print('No Hand') print('-------------------------') continue mark_list = [] for i in range(21): x = results.multi_hand_landmarks[0].landmark[i].x y = results.multi_hand_landmarks[0].landmark[i].y z = results.multi_hand_landmarks[0].landmark[i].z mark_list.append(x) mark_list.append(y) mark_list.append(z) mark_list.append(df['label'][idx]) df2.append(mark_list) print('-------------------------') df2 = pd.DataFrane(df2) df2.shape #---> (598, 64) df3 = pd.concat([df1, df2]) df3.shape #---> (1195, 64) df3.head() 無事に取得できてそうなのでこれで一旦csvファイルとして保存しておきます。 df3.to_csv('landmarkdata.csv', index=False) 検出ポイントの座標を集めることができたので次のモデル作成に移ります。 ②検出ポイントの座標からじゃんけんの手を予測するモデルを作る 集めた検出ポイントの座標データを使って、新しい手の画像からじゃんけんの手を予測するモデルを作成します。 今回はロジスティック回帰モデルを使ってみます。このモデルを選んだ理由は、 画像データだが特徴量を63個に減らしてある (予想だが)特に指先の座標についてじゃんけんの手ごとに差があり、線形分離が望めそう 各クラスへの所属確率に確率論的な意味が見いだせる です。特に3つ目がじゃんけん作成のときに使いたい特徴でした。モデルの複雑さが足りないようなら後で考え直すことにして、早速学習していきます。 #必要なライブラリをインポート import pandas as pd import numpy as np from sklearn.preprocessing import LabelEncoder from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression import pickle #作成したcsvファイルの読み込み df = pd.read_csv('landmarkdata.csv') #特徴量列とラベル列に分離 X = df.drop('63', axis=1) y = df['63'] #クラスラベルの数値化。変換の対応を確認したいので変換前後で表示しておく print(y[0], y[300], y[590]) #---> choki gu pa le = LabelEncoder() y = le.fit_transform(y) print(y[0], y[300], y[590]) #---> 0 1 2 #訓練データとテストデータに分割 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) #ロジスティック回帰モデルで学習を行い、テストデータのスコアを表示 lr = LogisticRegression()3 lr.fit(X_train, y_train) print(lr.score(X_test, y_test)) #---> 0.9832635983263598 思っていた精度よりもよくて嬉しい!イテレーション数オーバーのエラーも出ましたが十分だと判断し上限解放は行いませんでした。また、何回か実行してみてブレを観察しましたが、ほとんどが95%以上だったのでこのモデルでも十分と判断しました。 ついでに使いたかった所属確率についてもpredict_probaで確認します。 a = X_test.iloc[0, :] test = np.array([a[i] for i in range(len(a))]) pred = lr.predict(test.reshape(1, -1)) prob = lr.predict_proba(test.reshape(1, -1))[0][pred[0]] print('label:', s, ' prob.: ', prob[0][s]) #---> label: 1 prob.: 0.9132943271982226 結果からこのデータは91%の確率でグーであることがわかります。階層構造がちょっと面倒だなと感じます。。 満足したのでこのモデルを保存しておきます。 with open('./model/logistic.pkl', 'wb') as f: pickle.dump(lr, f) これでモデルを作成することができました。いよいよ最終段階に移っていきます。 ④じゃんけんする それぞれ準備が終わりいよいよ最終段階です。ここから未知の作業だったのでビビりながら実装していきます。 まずじゃんけんについては以下の記事を参考にさせていただきました。 初心者にはありがたい丁寧な解説でとても助かりました。ありがとうございました。 また、音声を扱うライブラリについては以下の記事を参考にしてSimpleaudioを選びました。 じゃんけんのタイミングを計るのに「再生中かどうかの判定ができる」というのが刺さりました。他のライブラリも触ってみたいです。ありがとうございました。 これらのありがたい記事や公式ガイドを参考にしながら作成していきます。 まずは前準備として必要なライブラリのインポート、ラベル対応表の作成、モデルの準備、検出器の準備を行います。 #必要なライブラリをインポート import numpy as np import cv2 import mediapipe as mp import simpleaudio import random import pickle #後で使う対応表の作成 label_dict = {0: 'b', 1: 'a', 2: 'c'} dic = {"a": "Rock", "b": "Scissors", "c": "Paper"} #前工程で作ったモデルの取得 with open('./model/logistic.pkl', 'rb') as f: model = pickle.load(f) #検出器のインスタンス化 hands = mp.solutions.hands.Hands( static_image_mode=True, max_num_hands=1, min_detection_confidence=0.5) 次にゲーム開始の部分です。(ここが初めてのことばかりで結構大変だった…) まずはゲーム開始として開始画面と掛け声の音声が流れるようにします。音声は「ぽん!」の後すぐに終わるので、音声が終了したらすぐにカメラで画像データを取得し、スタート画面は閉じるようにします。音声終了はSimpleaudioのis_playing()で判断してもらいました。ラグが少ないように実行の順番を考えながら書きましたがいい感じになっていることを期待します。 #表示する画像、再生する音声、カメラの準備 start_voice = simpleaudio.WaveObject.from_wave_file("./voice/jankenpon.wav") start_img = cv2.imread('./item/startimage.jpg', 3) cap = cv2.VideoCapture(0) #スタート画像の表示 cv2.imshow('start!', start_img) cv2.waitKey(1) #destroyWindowが実行されたらすぐに消えるように0より大きく音声再生時間より短く設定 #音声の再生 play_obj = start_voice.play() #音声の再生が終了するまでループ while True: if not play_obj.is_playing(): break #再生終了したらカメラを起動して画像取得 ret, frame = cap.read() #スタート画像の表示を終了 cv2.destroyWindow('start!') #カメラの画像から手を検出 image = cv2.cvtColor(cv2.flip(frame, 1), cv2.COLOR_BGR2RGB) results = hands.process(image) #カメラの終了 cap.release() これで画像が取得されたので、検出結果から画像の手がじゃんけんのどの手か予測し、PC側の手もランダムに決めてじゃんけんを実行、結果を表示します。 ここはtry構造を使って、手が検出されなかった場合や予測が不安定だった場合には「うまく読み取れませんでした」という画像が表示されるようにしました。 また、結果表示の部分では自分とPCの手の確認ができるように、結果の画面に手を表示させました。OpenCVの仕様上日本語だとうまくいかなかったので英語にしてます。 #ValueErrorがでない限りは以下の処理を行う try: #検出ポイントの座標を取得 mark_list = [] if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: for i in range(21): x = hand_landmarks.landmark[i].x y = hand_landmarks.landmark[i].y z = hand_landmarks.landmark[i].z mark_list.append(x) mark_list.append(y) mark_list.append(z) mark_list = np.array(mark_list) #ロジスティック回帰モデルを使ってじゃんけんの手を予測 #mark_listが空だとValueErrorになってtryから脱出 pred = model.predict(mark_list.reshape(1, -1)) prob = model.predict_proba(mark_list.reshape(1, -1))[0][pred[0]] #予測されたじゃんけんの手について、所属確率が弱ければValueErrorを起こしてtryから脱出 if prob < 0.85: raise ValueError #所属確率が85%以上ならばそれをプレイヤーの手と判断して続行 user = label_dict[pred[0]] user_choice = dic[user] #PCの手をランダムに選択 pc = dic[random.choice(["a", "b", "c"])] #judgeを適当な数で初期化し次のように変える #0:drow, 1:win, -1:lose judge = 3 if user_choice == pc: judge = 0 else: if user_choice == "Rock": if pc == "Scissors": judge = 1 else: judge = -1 elif user_choice == 'Scissors': if pc == "Paper": judge = 1 else: judge = -1 else: if pc == "Rock": judge = 1 else: judge = -1 #OpenCVの描画の仕様上日本語がだめなので英語で結果の文章を作成 ans1 = "Your Choice is %s" % user_choice ans2 = "PC's Choice is %s" % pc #じゃんけんの結果によって取得する画像を選択 image_path = './item/' voice_path = './voice/' if judge == 1: #勝った場合 voice_path = voice_path + 'win.wav' image_path = image_path + 'win.png' elif judge == 0: #あいこの場合 voice_path = voice_path + 'drow.wav' image_path = image_path + 'drow.png' elif judge == -1: #負けた場合 voice_path = voice_path + 'lose.wav' image_path = image_path + 'lose.png' #再生する音を表示する画像を取得 bgm = simpleaudio.WaveObject.from_wave_file(voice_path) result_img = cv2.imread(image_path, 3) #音楽の再生 play_obj = bgm.play() #画像に自分の手とPCの手を描画し、表示 cv2.putText(result_img, ans1, (80, 350), cv2.FONT_HERSHEY_COMPLEX, 2.5, (0, 0, 0), 3, cv2.LINE_AA) cv2.putText(result_img, ans2, (80, 500), cv2.FONT_HERSHEY_COMPLEX, 2.5, (0, 0, 0), 3, cv2.LINE_AA) cv2.imshow('RESULT', result_img) #3秒くらい経ったら自動でWindowを閉じる cv2.waitKey(3000) cv2.destroyAllWindows() #途中でValueErrorが起きた場合の処理 except ValueError : #画像を表示して1秒後くらいに閉じる result_img = cv2.imread('./item/sorry.png', 3) cv2.imshow('SORRY', result_img) cv2.waitKey(1000) cv2.destroyAllWindows() 説明のため分割しましたが、これらを合わせて実行するとじゃんけんゲームをすることができます! 苦労はしましたがやっぱりできたときに目に見えるのが嬉しいですね! 推しとじゃんけんというご褒美が最高に効きます 改善したいところ はやくアプリケーション化を勉強しろ あまり関数化する習慣がないので同じ処理をたくさん書いた印象。関数化する癖をつけたい。 動かしてみると精度が微妙かもしれない。画像サイズを使って正規化されているので、学習時と実行時の画像サイズが影響起こしそうな気がする。距離も一定の画像ばかりで学習させてしまったので、もう少しいろいろなデータを用意するか今あるデータを加工して対応できるようにするべきかもしれない じゃんけんアルゴリズムくらい頑張って考えてみてもよかったのでは?明確なサボり。。。 推しの画像でもテンション上がるけど推しのじゃんけんモーションがついた動画だったらさらにテンション上がると思う。音声付き動画データの取り扱いも学んでみたい
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Qiita APIを使ってある期間の記事情報を取得した話

はじめに  同期からQiita APIなるものがあることを知り、触ってみたいなと思ったのがきっかけです。少しですが私自身も記事を書いているので、どんな記事が読まれているのか、どんなタイトルに惹かれるのかなど解析できるのではないだろうかと思いました。本記事ではQiita APIを使って記事情報を取得する方法を紹介したいと思います。 Qiita APIって?  Qiita APIを使えば、Qiitaで公開されている記事情報(記タイトル、本文、投稿日、LGTMの数、コメントの数など)を取得することができます。しかも、コードもそこまで難しくはありません。私自身初めてQiita APIを触りましたが一日もあれば記事情報の取得まですることができました。Qiita APIについて詳細を知りたい人はこちらをご参照ください。 記事情報の取得コード  それでは、コードを紹介していきたいと思います。少し長くなってしまったので、「準備」と「実行」の2つに分けて紹介したいと思います。このコードを通して、2021年8月に作成されたQiita記事情報(タイトル、タグ、url、コメントの数、LGTMの数、作成日、記事を書いたユーザーID、本文)を取得します。 準備  実行の前に準備をしていきます。準備では、アクセストークンや取得する期間の設定などを行います。記事の取得にはアクセストークンが必要になります。こちらの記事の「Qiitaのアクセストークンの取得」を参考にしてアクセストークンを取得しましょう。取得したアクセストークンをtokenという変数に代入します。 準備 #ライブラリのインポート import numpy as np import pandas as pd import math import requests import json from tqdm.notebook import tqdm import time import datetime token = "+++++Please your token+++++" headers = { "content-type": "application/json", "Authorization": "Bearer " + token } # Qiitaのurl qiita_url = "https://qiita.com/api/v2" # タグでフィルターを掛けられる。例えばPythonとタグ付けされた記事のみの取得も可能です。 tag_no = "/items" wait_time = 3600 # この期間に作成されたQiitaの記事情報を取得 start = '2021-07-31' end = '2021-08-31' # 半月ごとの日付をリスト化 date_list = [d.strftime('%Y-%m-%d') for d in pd.date_range(start, end, freq="SM")] start_list = date_list[:-1] end_list = date_list[1:] columns = ["title", "tags", "article_url","comments_count", "likes_count", "created_at", "user_id", "text"] df = None コードの補足 wait_timeについてですが、記事情報へのアクセスリクエストは、認証しているユーザでは1時間に1000回まで、認証していないユーザーはIPアドレスごとに1時間に60回までだそうです。そのため、アクセス制限がきたら1時間(3600秒)待機するようにコーディングしました。 8月中の記事を取得したかったので便宜上、2021年7月31日からとしています。実際取得したのは標準時(日本は+9時間)の影響なのか、8月1日の9:00から8月31日の9:00までになっています。これは今後の課題です。 半月ごとの日付をリスト化していますが、途中経過などを見たくてこのようにしています。目的に対する本質的なものではありません。 実行の部分で取得したデータをdfにどんどん入れていきます。そのためにNoneを入れています。Noneを入れておくと最初に計算や代入、結合したものと同じ型になります。 実行  記事情報を取得してデータフレームにどんどん格納していくコードになっています。for文を入れ子にして実行しているので、もっと良い方法などあるかもしれません。 実行 for i in tqdm(range(len(start_list))): # 記事取得する期間の設定 start_date = start_list[i] end_date = end_list[i] query = "&query=created:>" + start_date + "+created:<" + end_date url_query = qiita_url + tag_no + "?" + query res = requests.get(url_query, headers=headers) if res.status_code == 403: after_time = datetime.datetime.fromtimestamp(time.time() + wait_time) print("アクセス制限です。少なくとも {} までは待機します。".format(after_time.strftime('%Y/%m/%d %H:%M:%S'))) time.sleep(wait_time) res = requests.get(url_query, headers=headers) total_count = int(res.headers['Total-Count']) print("{} から {} に作成された記事は {} 個です。".format(start_date, end_date, total_count)) jsondata = json.loads(res.text) page_count = math.ceil(total_count / 100) hundred = math.floor(total_count / 100) fraction = total_count %100 par_pages = [] for _ in range(hundred): par_pages.append(100) par_pages.append(fraction) for p in range(page_count): par_page = par_pages[p] p += 1 page = "page=" + str(p) res = requests.get(qiita_url + tag_no + "?" + page +"&per_page=" + str(par_page) + query, headers=headers) if res.status_code == 403: after_time = datetime.datetime.fromtimestamp(time.time() + wait_time) print("アクセス制限です。少なくとも {} までは待機します。".format(after_time.strftime('%Y/%m/%d %H:%M:%S'))) time.sleep(wait_time) res = requests.get(qiita_url + tag_no + "?" + page +"&per_page=" + str(par_page) + query, headers=headers) jsondata = json.loads(res.text) for item in jsondata: # 各記事を取得 article_data = [] item_id = item['id'] url = qiita_url + tag_no + "/" + item_id res = requests.get(url, headers=headers) if res.status_code == 403: after_time = datetime.datetime.fromtimestamp(time.time() + wait_time) print("アクセス制限です。少なくとも {} までは待機します。".format(after_time.strftime('%Y/%m/%d %H:%M:%S'))) time.sleep(wait_time) res = requests.get(url, headers=headers) json_content = json.loads(res.text) title = json_content["title"] tags = [] for j in range(len(json_content["tags"])): tags.append(json_content["tags"][j]["name"]) article_url = json_content["url"] comments_count = json_content["comments_count"] likes_count = json_content["likes_count"] created_at = json_content["created_at"] user_id = json_content["user"]["id"] text = json_content["body"] article_data.append([title, tags, article_url,comments_count, likes_count, created_at, user_id, text]) article_data = pd.Series(article_data[0], index = columns) article_data = pd.DataFrame([article_data]) df = pd.concat([df, article_data], axis = 0, ignore_index=True) コードの補足 1行目のtqdm()関数は進捗確認ができよく使っています。 「res.status_code == 403」ではアクセス制限であるという条件です。この場合の処理を下に書いており、time.sleep(wait_time)で1時間待機しています。 total_countは指定した期間にある記事の総数を表しています。1ページに100記事あり、ページをずらしながら記事の取得をしています。そこでページ数(page_count)とページごとの記事数(par_pages)という変数を作成しています。  これを実行すると、取得した記事情報がデータフレームとして入手できます。実行中には次の図のように表示されていました。 アクセス制限が来た際にはしっかりと1時間待機していますね。また、一ヶ月だけで8000記事弱の投稿があるようでこんなに投稿されていたのだと新しい発見もありました。 Word Cloudで簡単に可視化 WordColud import re import neologdn import texthero as hero # 文字列型にする関数 def set_str(text): return str(text) # タグを半角スペースでつなげていくコード def del_symbol(text): return text.replace("[","").replace(",", " ").replace("'", "").replace("]", "") tags = data_frame["tags"].apply(set_str).apply(del_symbol).apply(neologdn.normalize) # Word Coludの表示 hero.visualization.wordcloud(tags,font_path = "NotoSansCJKjp-hinted/NotoSansCJKjp-DemiLight.otf", colormap='viridis', width=500, height=500, background_color='black') コードの補足 textheroを用いてWord Cloudの結果を表示しています。Word Cloudは単語の出現頻度を可視化した図でどんな単語が多いのか視覚的にわかります。 デフォルトだと日本語を図に含めることができないので日本語表示できるフォントの入手が必要になります。こちらを参考にしてみてください。  これを実行した結果は次のような図になりました。日本語もしっかり表示されていますね(小さいですが・・・)。図を見るとやはりPythonが大きく表示されています。次いでAWSといったろころでしょうか。このように可視化するとインパクトがあり、面白いですね。 さいごに  本記事では、Qiita APIを使って記事情報の取得を行いました。アクセス制限やコーディングの技量のため時間がかかってしまいます(8000記事弱を取得するのに8時間から9時間かかっています)が、目的の情報を取得できたことは嬉しく思います。また、APIを使えばこのように簡単にできるので他のAPIも試してみたいですね。コード改良のアドバイスやおすすめAPIなどあれば教えていただくと大変助かります。  読んでくださりありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python初学者の備忘録 初級編⑤論理演算子について

←前項 論理演算子 基本 複数の式や値を比較し、boolを返す 以下の演算子がある 論理演算子 記号 説明 論理積 and(かつ) すべての条件がTrueのときTrueになる 論理和 or(または) 条件が1つでもTrueであればTrueになる 否定 not 上記の結果を反転させる 論理演算子の優先順位 「not」>「and」>「or」 出力結果 >>> 4 < 5 and 6 < 7 #>>> True >>> not (4 < 5 and 6 < 7) #>>> False # 上と同じ条件文 >>> not(4 < 5) and not(6 < 7) #>>> False >>> 4 < 5 or 6 < 7 #>>> True >>> not (4 < 5 or 6 < 7) #>>> False # 上と同じ条件文 >>> not(4 < 5) or not(6 < 7) #>>> False 次項→
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

matplotlibの箱ひげ図でもx軸を間隔尺度にしたい!

 分布を含めてデータを一覧したい時、箱ひげ図はかなり強力な武器になります。  しかし、基本的には箱ひげ図は、各データ間の大小をグラフに表しません(名義尺度)。順序を揃えることはあるかもしれませんが、それでもあくまで順序尺度どまりです。場合によっては、x軸同士の関係も見たいということがあるかもしれません。 やってみる  まず、以下のようなデータを考えます。あるゲームのランキングを国別にまとめたものです。  コードは次のような感じになります。(以下、importとかは省略) fig,ax = plt.subplots() ax.boxplot(distributions) ax.set_xticklabels(countries) plt.show()  例えば、国別に人口データあった場合、x軸を人口にしたいと考えます。boxplotでは、positionsを指定することによってできます。 fig,ax = plt.subplots() ax.boxplot(distributions, positions=populations) //positions plt.show()  結果  x軸のオーダーが大きすぎるため、箱ひげが針みたいになってしまいました。あと中国の人口がすごすぎて、それがなくとも純粋に見づらいです。箱の太さはデフォルトでは0.5 に指定されているため、データに合わせて調整が必要になりそうです。今回は、人口の方にlogをかけたり標準化をしたりして調整してみます。(箱の太さを調整したい場合、widhtsというパラメータで操作することができます。) log_populations = np.log(populations) fig,ax = plt.subplots() ax.boxplot(distributions,positions=log_populations) xfloor = math.floor(np.min(log_populations)) xceil = math.ceil(np.max(log_populations)) plt.xlim(xfloor,xceil) plt.show()  見づらい!!  箱ひげ図の横軸を自由にしてしまうと、このようなオーバーラップがあるから使われなかったのですね。あと、元々は単なる見栄えの問題であったはずの箱の太さが、まるで何か統計的意味を持ってしまうかのように見えてしまいます。これはグラフとしてあまりよくないです。  ちなみに、分布x分布というデータであった場合、二次元箱ひげ図というのも考案されていますが、同様の問題がある(オーバーラップのリスクが高い)ので実用的ではないようです。 悪あがき  とりあえずx軸がすごいことになっているので直します。 log_populations = np.log(populations) fig,ax = plt.subplots() ax.boxplot(distributions,positions=log_populations) xfloor = math.floor(np.min(log_populations)) xceil = math.ceil(np.max(log_populations)) ax.set_xticks(range(xceil)) ax.set_xticklabels(range(xceil)) plt.xlim(xfloor,xceil) plt.show()  あと棒も微妙に細くします。 log_populations = np.log(populations) widths = np.ones(len(distributions))*0.1 fig,ax = plt.subplots() ax.boxplot(distributions,positions=log_populations,widths=widths) xfloor = math.floor(np.min(log_populations)) xceil = math.ceil(np.max(log_populations)) ax.set_xticks(range(xceil)) ax.set_xticklabels(range(xceil)) plt.xlim(xfloor,xceil) plt.show()  今更ですが、どのデータがどこの国のものかわかりづらいので、グラフ上にラベルを表示することにします。実はけっこうこれが面倒くさくて、boxplotの命令一発でやるのが難しいので、for文の中で処理することになります。 log_populations = np.log(populations) fig,ax = plt.subplots() for d,c,l in zip(distributions,countries,log_populations): ax.boxplot(d,positions=[l],widths=[0.1]) # リストで指定することに注意 pos = (l+0.1,np.median(d)) ax.annotate(c,pos) xfloor = math.floor(np.min(log_populations)) xceil = math.ceil(np.max(log_populations)) ax.set_xticks(range(xceil)) ax.set_xticklabels(range(xceil)) plt.xlim(xfloor,xceil) plt.show()  うーん、最大限努力したけど、オーバーラップがある以上、やっぱり見づらい。 結論  箱ひげ図のx軸を間隔尺度にするのは、技術的には可能ですが、 オーバーラップがあると根本的に見づらい 箱の太さに統計的な意味があるように見えてしまう  というデメリットがあるので、あまり良いソリューションではなさそうです。ラベル別の分布を一覧するなら強力なツールなので、使い分けが重要ですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Collection個別にレンダリング画像を出力するようするスクリプト

Blender2.8以降ではビューレイヤーを使ってレンダリングに使用するコレクションの設定を切り替えることができます コレクション1つだけを有効にしたビューレイヤ―を作成することで、コレクション個別のレンダリング画像を出力するスクリプトを作成してみました 特定の文字列で始まるコレクションは操作を無視するようにしています(デフォルトでは#を設定) ライト等はシーンコレクション直下に置くか この文字を付けたコレクションの中に入れておくといいかと思います yRenderLayer_from_Collection.py import bpy scene = bpy.context.scene # 作成するノードの基準位置 node_origin = (0, 0) # レンダーノードと出力ノードの距離 node_w_offset = 300 # レンダーノード同士の縦の距離 node_h_offset = 120 # 保存先の基本パスの指定  "//"は.blendファイルと同一ディレクトリ base_path ="//comp/" # この文字で始まるCollectionは操作を無視する ignore_word = "#" def set_view_layer(target_collection): '''指定のコレクション1つだけ表示したビューレイヤ―作成''' layer_ = view_layers.new( target_collection.name ) # 対象のコレクション以外を不使用に設定 # で名前が始まるコレクションは無視 for Col in layer_.layer_collection.children: if Col.name.startswith(ignore_word): continue elif Col.name == target_collection.name: Col.exclude = False else: Col.exclude = True return (layer_ ) def meke_RenderLayer_node( node_tree, Rrnder_Scene, view_Layer, name, position ): '''レンダーレイヤノードの作成''' RL_Node = node_tree.nodes.new('CompositorNodeRLayers') RL_Node.name = name RL_Node.location = position RL_Node.scene = Rrnder_Scene RL_Node.layer = view_Layer.name #ビューレイヤ名 RL_Node.show_preview = False return(RL_Node) def make_PNG32Output_node(node_tree, name, base_path, position): '''ファイルアウトプットノードの作成''' File_Node = node_tree.nodes.new('CompositorNodeOutputFile') File_Node .name = name File_Node .location = position File_Node .base_path = base_path #初期設定の入力スロットを削除 File_Node .file_slots.remove(File_Node .inputs[0]) #8bitRGBAのPNGに設定 File_Node .format.color_depth = "8" File_Node .format.color_mode = "RGBA" File_Node .format.file_format = "PNG" return (File_Node ) # シーンコレクション直下にあるコレクションの取得 collections = scene.collection.children view_layers = scene.view_layers # コレクション1つだけ表示したビューレイヤ―を作成 Col_layers = [] for target_collection in collections: if not target_collection.name.startswith(ignore_word): layer_ = set_view_layer(target_collection) Col_layers.append(layer_) # ビューレイヤ個々でレンダリング出力するコンポジットを作成 # コンポジションノードの取得 node_tree = scene.node_tree scene.use_nodes = True # ファイルアウトプットノードの作成 File_Output = make_PNG32Output_node(node_tree, 'File_Output', base_path, node_origin) # ビューレイヤ個々でレンダーノードの作成 Render_nodes = [] for i,layer_ in enumerate(Col_layers): position = (node_origin[0] -node_w_offset, node_origin[1] + node_h_offset *-i) node_ = meke_RenderLayer_node( node_tree, scene, layer_, layer_.name, position ) # ファイルアウトプットノードのスロットを追加 f_path = "%02d_%s_####" % (i, layer_.name) file_Slot = File_Output.file_slots.new(f_path) # レンダーレイヤとファイルアウトプットノードのスロットと接続 node_tree.links.new(node_ .outputs[0], file_Slot) Render_nodes.append(node_) # 作成したレンダーレイヤを削除する場合の処理 ''' for layer_ in Col_layers: scene.view_layers.remove(layer_) node_tree.nodes.remove(File_Output) for node_ in Render_nodes: node_tree.nodes.remove(node_) #''' コレクションはアウトライナ上で並び順が取得できるので上から順に番号を振るようにもしてあります 動画のフッテージ用に連番画像を書き出す場合には # ファイルアウトプットノードのスロットを追加 f_path = "%02d_%s/%s_####" % (i, layer_.name, layer_.name) といった具合にして コレクション名のフォルダの中に個々の画像ファイルが入るようにした方がいいかもしれません 現場に合わせてカスタマイズしてみてください
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Collection個別にレンダリング画像を出力するようにするスクリプト

Blender2.8以降ではビューレイヤーを使ってレンダリングに使用するコレクションの設定を切り替えることができます コレクション1つだけを有効にしたビューレイヤ―を作成することで、コレクション個別のレンダリング画像を出力するスクリプトを作成してみました 特定の文字列で始まるコレクションは操作を無視するようにしています(デフォルトでは#を設定) ライト等はシーンコレクション直下に置くか この文字を付けたコレクションの中に入れておくといいかと思います yRenderLayer_from_Collection.py import bpy scene = bpy.context.scene # 作成するノードの基準位置 node_origin = (0, 0) # レンダーノードと出力ノードの距離 node_w_offset = 300 # レンダーノード同士の縦の距離 node_h_offset = 120 # 保存先の基本パスの指定  "//"は.blendファイルと同一ディレクトリ base_path ="//comp/" # この文字で始まるCollectionは操作を無視する ignore_word = "#" def set_view_layer(target_collection): '''指定のコレクション1つだけ表示したビューレイヤ―作成''' layer_ = view_layers.new( target_collection.name ) # 対象のコレクション以外を不使用に設定 # で名前が始まるコレクションは無視 for Col in layer_.layer_collection.children: if Col.name.startswith(ignore_word): continue elif Col.name == target_collection.name: Col.exclude = False else: Col.exclude = True return (layer_ ) def meke_RenderLayer_node( node_tree, Rrnder_Scene, view_Layer, name, position ): '''レンダーレイヤノードの作成''' RL_Node = node_tree.nodes.new('CompositorNodeRLayers') RL_Node.name = name RL_Node.location = position RL_Node.scene = Rrnder_Scene RL_Node.layer = view_Layer.name #ビューレイヤ名 RL_Node.show_preview = False return(RL_Node) def make_PNG32Output_node(node_tree, name, base_path, position): '''ファイルアウトプットノードの作成''' File_Node = node_tree.nodes.new('CompositorNodeOutputFile') File_Node .name = name File_Node .location = position File_Node .base_path = base_path #初期設定の入力スロットを削除 File_Node .file_slots.remove(File_Node .inputs[0]) #8bitRGBAのPNGに設定 File_Node .format.color_depth = "8" File_Node .format.color_mode = "RGBA" File_Node .format.file_format = "PNG" return (File_Node ) # シーンコレクション直下にあるコレクションの取得 collections = scene.collection.children view_layers = scene.view_layers # コレクション1つだけ表示したビューレイヤ―を作成 Col_layers = [] for target_collection in collections: if not target_collection.name.startswith(ignore_word): layer_ = set_view_layer(target_collection) Col_layers.append(layer_) # ビューレイヤ個々でレンダリング出力するコンポジットを作成 # コンポジションノードの取得 node_tree = scene.node_tree scene.use_nodes = True # ファイルアウトプットノードの作成 File_Output = make_PNG32Output_node(node_tree, 'File_Output', base_path, node_origin) # ビューレイヤ個々でレンダーノードの作成 Render_nodes = [] for i,layer_ in enumerate(Col_layers): position = (node_origin[0] -node_w_offset, node_origin[1] + node_h_offset *-i) node_ = meke_RenderLayer_node( node_tree, scene, layer_, layer_.name, position ) # ファイルアウトプットノードのスロットを追加 f_path = "%02d_%s_####" % (i, layer_.name) file_Slot = File_Output.file_slots.new(f_path) # レンダーレイヤとファイルアウトプットノードのスロットと接続 node_tree.links.new(node_ .outputs[0], file_Slot) Render_nodes.append(node_) # 作成したレンダーレイヤを削除する場合の処理 ''' for layer_ in Col_layers: scene.view_layers.remove(layer_) node_tree.nodes.remove(File_Output) for node_ in Render_nodes: node_tree.nodes.remove(node_) #''' コレクションはアウトライナ上で並び順が取得できるので上から順に番号を振るようにもしてあります 動画のフッテージ用に連番画像を書き出す場合には # ファイルアウトプットノードのスロットを追加 f_path = "%02d_%s/%s_####" % (i, layer_.name, layer_.name) といった具合にして コレクション名のフォルダの中に個々の画像ファイルが入るようにした方がいいかもしれません 現場に合わせてカスタマイズしてみてください
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

数直線原理主義(Number Line Fundamentalism)」からの脱却

これまでの投稿内容のある種のまとめ。 ①観測線(Observated Line)概念からの出発。 観測原点(Observated Origin)0と観測極限(Observated Limit)∞を結ぶ非負の連続実数列(Consecutive Real Sequence)rから出発する。ここで観測結果集合(Observated Result Set)rは観測原点0そのものも観測極限∞そのものも含まない開集合(Open Set)と規定される。 0< r <∞(r \in \mathbb{R}) ②加法単位元(Additive Identity Element)0概念と乗法単位元(Multiplication Identity Element)1概念の追加。 加法単位元(Additive Identity Element)0と乗法単位元(Multiplication Identity Element)1を以下の様に規定する。 ∞-∞=0(加法単位元)\\ * トートロジー(Tautology=同内容反復)式∞=∞の変形\\ \\ \frac{∞}{∞}=1(乗法単位元)\\ * 等尺数列(Isometric Sequence)式1×∞=∞の変形 ③加法実数群(Additive Real Group)概念=スカラー(Scalar)概念の追加。 連続実数列rと加法単位元0とその反数(Additive Inverse)-rの概念を加え加法実数群(Additive Real Group)とする。合わせてこれをスカラー(Scalar)と規定し、族集合(Family Set)を記し分ける際の添字集合(Index set)nなどで用いる事にする。 スカラー (数学) - Wikipedia (\mathbb{R},+)=-∞<-r<0<r<+∞\\ s=(\mathbb{R},+) ④乗法実数群(Multiplicative Real Group)概念の追加。 乗法単位元1を中心に外側にn倍、内側に逆数(Multiplicative Inverse)たる$\frac{1}{n}$倍の半径rの同心円を配置した極座標系(Polar Coordinates System)を規定し、これを乗法実数群(Multiplicative Real Group)の定義とする。 \begin{eqnarray*} (\mathbb{R},×)&=&0(=\frac{1}{∞})<\frac{1}{n}<1(=\frac{n}{n})<n<∞(乗除算)\\ &=&0(=r^{-∞}=\frac{r}{∞})<r^{-n}(=\frac{1}{r^n})<1(=r^0=\frac{r}{r})<r^n<∞(r=^{+∞})(冪算)\\ \end{eqnarray*} 【Pyrhon演算処理】同心集合①乗法的同心集合とは? 関数$y=2^{\frac{n}{2}}$が生成する同心円集合(正方形に内接/外接) 関数$y=2^n$が生成する同心円集合(正三角形/正六角形に内接/外接) 関数$y=e^n$(自然指数関数)が生成する同心円集合(さらに半径増減の勾配が急に) 同時に小数点下も表現可能な十進数表現概念を導入しておこう。より厳密には上掲の「幾何学上における正多角形と内接/外接円問題」と密接に関連してくる剰余類(Cosets=傍系)の概念導入が欠かせない。剰余類 - 物理のかぎしっぽ剰余類2 - 物理のかぎしっぽ合同式(mod)の意味とよく使う6つの性質 - 学びTimes(http://hooktail.sub.jp/algebra/Remainder/) 整数部n桁、少数部m桁の十進数表現a_nb_mを以下の様に規定する。\\ a_n(a_1,…,a_n) \in \mathbb{Z} \land 0≦a_n≦9(\mathbb{Z} mod 10)\\ b_m(b_1,…,b_m) \in \mathbb{Z} \land 0≦b_m≦9(\mathbb{Z} mod 10)\\ すなわち\\ a_n,b_m \in (0,1,2,3,4,5,6,7,8,9)\\ この時\\ \begin{eqnarray*} a_nb_m&=&\sum_{n=1}^{n}a_n 10^n+\sum_{m=1}^{m}b_m 10^{-m}\\ &=& a_1 10^n+a_2 10^{n-1}+…+a_n 10^{0}+b_1 10^{-1}+…+b_m 10^{-m} \end{eqnarray*}\\ ただしn,m \in a_nb_m なるほど「ベクトル空間(Vector Space)において超越的に存在する」スカラーは、この様に一次結合的表現(Linear Combination like Expression)によって再帰的かつ離散的に規定される。「十の位」や「百の位」や「千の位」が表現可能とはそういう訳だったのである(1の位が$a_n 10^0$になる点に注意)。 ベクトルと異なり向きの概念を備えないとされるスカラーだが、この様にその表記に用いられる10進法($10^n$を法とする剰余類の無限連鎖による元の数の近似)そのものの表現に既に(互いの直交を前提とする)標準基底(Standard Basis)(1,0,0,…,0),(0,1,0,…,0),(0,0,1,…,0),…,(1,0,0,…,0)の類似概念が導入されている辺りが実に興味深い。正規直交基底 - Wikipedia いずれにせよこうして等尺(Isometric Scale)、指数尺(Exponential Scale)、対数尺(Logarithmic Scale)の概念がまとめて使用可能となる。 ⑤指数写像(Exponential Map)/対数写像(Logarithmic Map)概念の追加。 ところで乗法実数群はは加法実数群の指数写像(Exponential Map)であり、かつ加法実数群は乗法実数群の対数写像(Logarithmic Map)である(加法実数群における乗除算/冪算が乗法実数群における加減算/乗除算に対応する)。 【数理考古学】常用対数表を使った計算 指数写像(加法実数群→乗法実数群) 【Pyrhon演算処理】同心集合③環概念と指数/対数写像概念の導入 加法実数群 乗法実数群 0 -∞ 0 1 -1 exp(-1) 2 0 1 3 1 exp(+1) 4 +∞ ∞ 対数写像(乗法実数群→加法実数群) 【Pyrhon演算処理】同心集合③環概念と指数/対数写像概念の導入 乗法実数群 加法実数群 0 0 -∞ 1 exp(-1) -1 2 1 0 3 exp(+1) 1 4 ∞ +∞ ⑥加法実数群概念と乗法実数群概念の実数環概念(Real Ring Concept)への統合 この特徴に着目して乗法実数群(角度の概念が導入される以前の極座標系)を水平軸、加法実数群(一次元デカルト座標系)を垂直軸に取ったある種の円筒座標系(Cylindrical Coordinate System)を実数環(Real Ring)と規定すれば、水平軸が半径1の時に垂直軸の傾き(勾配=Slope)が実数列(加法実数群)のそれと一致する。 群同型 Wikipedia 加法整数群$(\mathbb {Z},+)$は加法実数群$(\mathbb{R},+)$の部分群であり、商群$\frac{\mathbb{R}}{\mathbb{Z}}$は、同型写像$f(x+\mathbb {Z})=e^{2πxi}(x \in \mathbb{R} \land 0 \leqq x \leqq 2π)$によって絶対値1の乗法複素数群$S^1$に同型である: \frac{(\mathbb{R},+)}{(\mathbb{Z},+)} \cong S^1 すなわち… e^{2πi}(exp(0+6.283185i))=\cos(2π)+\sin(2π)i=1+0i\\ e^{πi}(exp(0+3.141593i))=\cos(π)+\sin(π)i=-1+0i\\ -e^{πi}(-exp(0+3.141593i))=-\cos(π)-\sin(π)i=1+0i または…・ -1^n=±i^{2n}\\ -1^1=±i^{2}=-1\\ -1^2=±i^{2*2}=1 この様な形で乗法加法群と乗法実数群の座標軸が直交していると考えると、それから逆算して自然数(Matural)集合/列$\mathbb{N}=(1,2,3,…,∞)$や整数(Integer)集合/列$\mathbb{Z}=(-∞,…,-3,-2,-1,0,1,2,3,…,+∞)$の概念を規定し、かつまたそれらが(10進数導入を前提とする)小数点下を直接は含まず(乗法的逆数概念の反映たる)有理数(Rational)集合/列$\mathbb{Q}$や(任意の一次元実数列上の1点を中心とする極座標系が元数列に与える影響を演算する)複素数(Complex)概念$\mathbb{C}$に拡張される過程がより明確化出来る。一時結合表現の大源流としての複素数表現/四元数表現 さらに指数写像・対数写像概念の適用を続ければ、円筒座標系と球面座標系(Spherical Coordinate System)の間の往復も可能となる。いわゆるメルカトル図法(Mercator Projection)の発想… 【Python画像処理】メルカトル図法と正距方位図法 そもそも数学的対象(Mathematical Object)とは? そもそも数学の世界において数学的対象(Mathematical Object)と認識される為には、観測結果集合/列(Observated Result Set/Sequence)rとして観測されただけでは不十分で、それから抽出された特徴(Feature=機械学習における学習対象等)を再現(近似)する演算(Operation)と組み合わせた群論的表現(Group Theory Expression)(r,○)などに発展させられる必要があります。 数学的対象 - Wikipedia もちろんここでの再現/近似は完璧とは限らず、実際歴史上幾度も更新されてきましたし、これからも更新されていく事でしょう。その総体こそが「数理そのもの」に対する数学の立場であり、例えば上掲の様に算数初学者の頃から慣れ親しんできた「数直線概念(Number Line Concept)」から、それと紐付けて覚えさせられてきた以下の様な集合/列概念(Set/Sequence Concept=最も原始的な数学的対象)を「解放」する為だけにも上掲の様な手間が必要となったのです。 ◇数直線ほど不可解な線はない◇ - AIRnet 自然数集合/列(Natural Set/Sequence)$\mathbb{N}$ 整数集合/列(Integer Set/Sequence)$\mathbb{Z}$ 有理数集合/列(Rational Set/Sequence)$\mathbb{Q}$ 実数集合/列(Rational Set/Sequence)$\mathbb{R}$ 複素数集合/列(Complex Set/Sequence)$\mathbb{C}$ 集合(Set)概念と数列(Sequence)概念を峻別するのは順序関係(Ordered Relation)の有無と考えられます。そして上掲の考え方を援用するなら、それを問える様になるのは群論(Group Theory)概念の導入され数列の定義が規定される③以降という事になりそうです。 【順序集合】反射性/非反射性と対称性/非対称性と推移性/非推移性の関係定義 とりあえず以下続報…
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

物体検出の学習済みモデル使ってみた

学習済みモデルのダウンロード openimagev4と呼ばれるデータセットで訓練したSSD(Single Shot MultiBox Detector)というモデルを使ってみました openimagev4 600種類のクラスはここから確認できます https://storage.googleapis.com/openimages/2018_04/class-descriptions-boxable.csv 実際に使ってみる https://tfhub.dev/google/openimages_v4/ssd/mobilenet_v2/1 圧縮されたフォルダを展開してロードするだけです。 modelpath = "./openimages_v4_ssd_mobilenet_v2_1" #"./faster_rcnn" model = hub.load(modelpath).signatures['default'] 入力はTensorです def load_img(path): img = tf.io.read_file(path) img = tf.image.decode_jpeg(img, channels=3) return img localpath = os.path.join(dpath, fname) image = Image.open( localpath ) tfimg = load_img( localpath ) converted_img = tf.image.convert_image_dtype(tfimg, tf.float32)[ tf.newaxis, ... ] result = model(converted_img) 検出結果 速度と精度 速度だと yolo > ssd > faster-rcnn 精度は faster-rcnn > ssd > yolo という認識です 480x270pxの画像を使って、faster-rcnnという精度重視のモデルと比較してみました モデル/速度平均値(秒/枚) ssd 0.2 faster-rcnn 2 標準偏差は0.001程度でほぼ無視できます 時間あれば適合率も出しますね 残念なとこ 転移学習はできないみたいです。自分の知る限り転移学習したければこれ(Yolov3)しかありませんね https://github.com/pythonlessons/TensorFlow-2.x-YOLOv3 そーす
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【順序集合】反射性/非反射性と対称性/非対称性と推移性/非推移性の関係定義

反射関係 -Wikipedia 推移的で無反射的な関係は、非対称関係で強半順序関係となる。一方、推移的で反射的な関係は(半順序関係や同値関係といった特殊例も含め)単なる前順序(擬順序)関係となる。有限集合では前者よりも後者の方が多い。 非対称関係(Asymmetric relation -Wikipedia) 原義としては対称的でない二項関係を意味するが、場合によっては「Xにおける関係Rが非対称であるとは、Xの属する全ての元aおよびbについて、aからbへの関係が成り立つ時はbからaへの関係が成り立たない場合を指す」なる狭義で説明される。 $\forall a,b\in X,\ aRb\;\Rightarrow \lnot (bRa)$ この意味合いにおける非対称関係は、反対称的であると同時に非反射的でもある。推移関係では非対称性と非反射性が等価となり、この場合の非対称性は上の狭い意味の定義を包含するが、逆は成り立たない。  一方、空集合は後者の意味で非対称的であると同時に対称的に振る舞う。 過去投稿で定義した空和概念(元の総和は常に0)と空積概念(元の総積は常に1)を「指数・対数写像」概念で統合した空環概念(Empty Ring Concept)で考えてみると、それが認識体系上の限界、すなわち「数理的に有意味な要素を何も検出出来てない状況下における認識可能範囲外全て」に対応する都合上「非反射性要素=元に含まれない非元」は自明の場合(Trival Case)としてまとめて(順序尺度など到底成立しない)非推移関係に分類され、そもそもさらに反射性/非反射性や対称性/非対称性を問う事自体が出来ない。 【Python演算処理】環論に立脚した全体像再構築①空環と実数環 空和概念(Empty Sum Concept)…「∞-∞=加法単位元0」なる方便から出発する「平均と分散」「共役」概念の大源流 空積概念(Empty Product Concept)「∞/∞=乗法単位元1」なる方便から出発する「反比例関係xy=1」「指数・対数写像」概念の大源流 空和概念の空積概念への「指数写像」。既に(表面を均等尺で敷き詰めた)「球面座標系」や(表面を対数尺で敷き詰めた)半径1の単位円を赤道、0と∞をそれぞれ対蹠(北極点や南極点)に対応させる「リーマン球面(Riemann Sphere)」を扱う幾何学的操作が用いられているが、実数環段階と異なり空環段階ではまだ「赤道に該当する半径1の単位円」が検出出来ていない。リーマン球面 - Wikipedia 空積概念の空和概念への「対数写像」。既に(表面を均等尺で敷き詰めた)「球面座標系」を扱う幾何学的操作、すなわち「リーマン球面」を(赤道に対応する)半径$\frac{π}{2}$と(観測限界∞に対応する)半径πの二重同心円状態への展開が用いられているが、実数環段階と異なり空環段階ではまだ「赤道に該当する半径$\frac{π}{2}$の円」が検出出来ていない。【Python画像処理】メルカトル図法と正距方位図法 ところが数学の世界における反射性/非反射性と対称性/非対称性と推移性/非推移性の関係定義は(空集合の振る舞いを含め)はこの制約に縛られていない様に見えます。果たしてどうやってそれを実現しているのでしょう? 順序集合(Ordered Set) -Wikipedia 「順序」の概念が定義された集合のことで、「順序」とは大小、高低、長短等の序列に関わる概念を抽象化した二項関係を指す。ただしここでいう順序とは、その集合の任意の2つの元に対して必ずしも定まっているとは限らず、両者が「比較不能」であることもありうる。 比較不能の場合を許容する順序集合として典型的なのが「半順序集合(Partially Ordered Set, Poset)である。特に、半順序集合で全ての2元が比較可能であるものを「全順序集合(totally ordered set)」という。 その定義(同値関係を導出する同値律との微妙な定義違いに注意) 集合Pについて「≤」をP上で定義された二項関係とする。かかる集合(P,≤)は台集合(Underlying Set) あるいは台(Support)とも呼ばれる。紛れがなければ≤ を省略し、集合Pを(以下のいずれかの意味で)順序集合という。順序集合(P,≤)に対し「≤」を台P上の順序関係ともいう。 反射律:Pの任意の元aに対し、a≤aが成り立つ($\forall a \in P,a≤a$)。 推移律:Pの任意の元a,b,cに対し、a≤bかつb≤cならばa≤cが成り立つ($\forall a,b,c \in P,a≤b \land b≤c \to a≤c$)。 反対称律:Pの任意の元a,bに対し、a≤bかつb≤aならばa=bが成り立つ($\forall a,b \in P,a≤b \land b≤a \to a=b$)。 全順序律:Pの任意の元a,bに対し、a≤bまたはb≤aが成り立つ($\forall a,b \in P,a≤b \lor b≤a$)。 「≤」が全順序律を満たさない場合には「a ≤ b」でも「b ≤ a」でもない場合が想定され、この時aとbは「比較不能 (incomparable)」であるという。 「≤」が反射律と推移律を満たすとき「≤」をP上の前順序という。 「≤」が前順序でありさらに反対称律を満たすとき「≤」をP上の半順序という。 「≤」が半順序でありさらに全順序律を満たすとき 「≤」をP上の全順序という。 「≤」が前順序であるとき (P, ≤) を前順序集合という。同様に「≤」が半順序なら (P, ≤) は半順序集合、全順序なら (P, ≤) は全順序集合という。 多くの数学の分野では半順序集合を主に扱うので、単に順序あるいは順序集合といった場合はそれぞれ半順序、半順序集合を意味する場合が多いが、分野によっては、主な対象が半順序集合でなく前順序集合や全順序集合である場合があり、そのような分野では前順序集合や全順序集合の意味で「順序集合」という言葉が用いられることがあるので注意が必要である。 ここでは順序関係を記号「≤」で表したが、必ずしもこの記号で表現する必要はない。実数の大小を表す記号「≤」と区別するため、順序の記号として$\prec$や$\ll$を使うこともある。 順序集合の実例(一部抜粋) 実数全体の集合$\mathbb{R}$およびその部分集合(例えば、自然数全体の集合$\mathbb{N}$,整数全体の集合$\mathbb{Z}$, 有理数全体の集合$\mathbb{Q}$)は、通常の大小関係により全順序集合となる。 一方、複素数全体の集合$\mathbb{C}$には複素数の乗法と"両立"する全順序は存在しない(順序体でない)。分岐点(数学)- Wikipedia 自然数全体の成す集合は整除関係を順序として半順序集合である。剰余類 - Wikipedia【分解する物語(2)】整除関係 複素数や剰余類のケースでも、単に全順序を入れるだけであれば、直積集合R×Rに辞書式順序(Lexicographical Order)を定めることができる。辞書式順序 - Wikipedia どうやら大雑把には(通常多価関数で表現される)複素数や剰余類の類こそが「半順序集合」の典型的イメージの一つで、その範囲についてなら「(周期管理と周回管理を切り離した)円筒座標系」や「(10進数の様に桁上がり/桁下り概念を備えた)P進数」概念を方便として導入する事によって全順序集合として扱い得るといった粗雑な理解で乗り越えられそうな気がしてきました。 【Python演算処理】環論に立脚した全体像再構築①空環と実数環 【初心者向け】N進法とp進数 そのうちPythonでの実装を検討したいと考えています。そんな感じで以下続報…
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【python, jupyter lab】ファイルがあるのにno such file or directoryが出たら

import os path = os.getcwd() print(path) # 例: /workspace を実行してみてください(カレントディレクトリを表示します)。 なぜかカレントディレクトリが、そのipynbファイルの置き場所じゃなかったりすることがあります。 出力を確認してみて、 想定していたカレントディレクトリ = 出力 ではなかった時は、以下を実行。 os.chdir('/workspace/hoge/') # ← 変更したいディレクトリを入れてください。 で、カレントディレクトリを変えればOKです。 念のためチェック path = os.getcwd() print(path) #/workspace/hoge 簡単な話ですが、ipynbファイルの置き場所を無条件にカレントディレクトリとして参照するものだと思っていたので、案外はまりました。 コード一部 引用:https://note.nkmk.me/python-os-getcwd-chdir/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS LambdaでサクッとAPIを叩きたい

AWS マネジメントコンソール上でLambdaを実装して、APIを叩きたい サクッとWEBAPIをLambdaで叩きたい人向けです。 AWSのコンソール上のコードエディターのみで作業を完結させたいときに。 こんな人向け ・WEBAPIを実行したい ・AWSマネジメントコンソールのみで作業を完結させたい ・headerに認証キーを付けたい ・認証キーは環境変数に入れておきたい ・返り値はステータスコードだけ取れればよい 環境情報 AWS Lambda ランタイム:Python3.9 ソースコード(PUT API) Lambda 標準の同包モジュールのみでの実装するため、 AWS Lambda コードエディター上に下記を張り付けるだけです。 import os import json import urllib.request def lambda_handler(event, context): #PUT API url_str = "https://APIURL/" headers = {"Authorization" : os.environ.get('BearerToken')} data = "data" request = urllib.request.Request(url_str, data.encode('utf-8'), method='PUT', headers=headers) response = urllib.request.urlopen(request) res_code = response.getcode() # PRINT STATUS CODE print(res_code) return { 'statusCode': res_code } 環境変数の設定 AWS Lambda上、「設定」タブ内にある「環境変数」を設定しましょう。 環境変数の名称は、ソースコードの"BearerToken"です。 出会ったエラー TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str. dataはstr型ではなくbytes型である必要があります。 スタックオーバーフローで同じエラーを抱えている人に多く出会いました。 結論としてはdataをエンコードしてあげる必要があります。 おわりに ちょっと確認したいだけだから5分でできると思ったら15分掛かったので記事にしました。 久しぶりのpythonは、アレっとなりますね。 開発初期の検証などに。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

等高線やCTスキャンなどの断面図から3Dモデルを自作する方法【Blender2.9】

https://youtu.be/UmmwD0w4Xio この動画の内容をスクリプトにしたものです。 import bpy #bpyというモジュールを使いますという宣言 obj = bpy.context.view_layer.objects.active #アクティブなオブジェクトをobjとする obj_name = obj.name #objの名前をobj_nameとしてメモっておく obj.name = "p_c" #objの名前をp_cに変更 (pre_curveの略) bpy.data.objects['p_c'].select_set(True) #オブジェクト "p_c"を選択 obj = bpy.context.window.scene.objects['p_c'] #”p_c”という名前のオブジェクトをobjとする bpy.context.view_layer.objects.active = obj #obj (="p_c")をアクティブにする bpy.ops.object.modifier_apply(modifier="Subdivision") #サブディビジョンサーフェスを適用 (必要なら) bpy.ops.object.mode_set(mode="EDIT") #編集モードに切り替え bpy.ops.mesh.separate(type='LOOSE') #構造的に分離したパーツで分割 bpy.ops.object.mode_set(mode="OBJECT") #オブジェクトモードに切り替え bpy.ops.object.convert(target="CURVE") #カーブに変換 bpy.context.object.data.use_stretch = True #カーブの設定のストレッチを有効にする bpy.context.object.data.use_deform_bounds = True #カーブの設定の境界固定を有効にする edge_obj=bpy.data.objects['edge'] #”edge”という名前のオブジェクトをedge_objとする #(重要)edgeオブジェクトはX個の頂点を持つ棒状のオブジェクトです→ #→前もって用意しておく必要があります(手作業でも作れますが一番最後にスクリプトでの作り方を載せてあります) bpy.context.view_layer.objects.active = edge_obj #edge_objをアクティブにする edge_obj.select_set(True) #edge_objを選択する bpy.ops.object.modifier_add(type='CURVE') #カーブモディファイアを追加 bpy.context.object.modifiers["Curve"].object = bpy.data.objects["p_c"] #”p_c”という名前のカーブをカーブモディファイアに設定する bpy.context.object.modifiers["Curve"].deform_axis = 'POS_Z' #変形軸をZ軸にする #↑の処理を、p_cだけではなく、p_c.001、p_c.002、、にも同様に行っていく。 slice_n = 30 #階層の数を30とする (実際の階層数を超えていればなんでもOK) #★★繰り返し処理Aはここから for i in range(1,slice_n+1): #1から ↑で決めた階層数(slice_n)まで処理を繰り返す curve_name = "p_c." + str(i).zfill(3) #p_c .001、p_c.002、、をcurve_nameとする #zfill (3)は1を001、2を002、、にする関数 p_c_2 = bpy.data.objects.get(curve_name) #curve_nameという名前のオブジェクトをp_c_2とする #↓そんな名前のオブジェクトが存在するか確認する if p_c_2 == None: #p_c .XXXが存在しなくなったら、 break #繰り返し処理を終了する p_c_2 = bpy.context.window.scene.objects[curve_name] bpy.context.view_layer.objects.active = p_c_2 #p_c_2をアクティブにする bpy.data.objects[curve_name].select_set(True) #選択する bpy.context.object.data.use_stretch = True #ストレッチを有効にする bpy.context.object.data.use_deform_bounds = True #境界固定を有効にする #★★★ここで一区切り★★★ for ob in bpy.context.scene.objects: #全てのオブジェクトを非選択状態に設定する ob.select_set(False) #edge_obj =bpy.data.objects['edge'] “edge”という名前のオブジェクトをedge_objとする bpy.context.view_layer.objects.active = edge_obj #edge_objをアクティブにする edge_obj.select_set(True) #edge_objを選択する bpy.ops.object.duplicate_move(OBJECT_OT_duplicate=None, TRANSFORM_OT_translate=None) #edgeを複製する (Shift+Dの操作) bpy.context.object.modifiers["Curve"].object = bpy.data.objects[curve_name] #カーブモディファイアを設定し 、カーブをcurve_name(p_c.XXXとか)を設定 bpy.context.object.modifiers["Curve"].deform_axis = 'POS_Z' #変形軸をZ軸に設定 #★★繰り返し処理Aはここまで edge_obj=bpy.data.objects['edge'] #edgeという名前のオブジェクトをedge_objとする bpy.context.view_layer.objects.active = edge_obj #edge_objをアクティブにする edge_obj.select_set(True) #edge_objを選択する bpy.ops.object.modifier_apply(modifier="Curve") #カーブモディファイアを適用する #↑の処理を、edgeだけではなく、edge.001、edge.002、、にも同様に行っていく。 #★★繰り返し処理Bはここから for i in range(1,slice_n+1): #1から ↑で決めた階層数(slice_n)まで処理を繰り返す edge_name = "edge." + str(i).zfill(3) #edge .001、edge.002、、をedge_nameとする #zfill (3)は1を001、2を002、、にする関数 edge_2 = bpy.data.objects.get(edge_name) #edge_nameという名前のオブジェクトをedge_2とする #↓edge.XXXが存在するか確認する if edge_2 == None: break #存在しなかったら繰り返しを終了する edge_2.select_set(True) #edge_2を選択する bpy.context.view_layer.objects.active = edge_2 #edge_2をアクティブにする bpy.ops.object.modifier_apply(modifier="Curve") #カーブモディファイアを適用 #★★繰り返し処理Bはここここまで bpy.context.view_layer.objects.active = edge_obj #edge_objをアクティブにする #ここまでの流れでedge ~edge.XXXはすでに全て選択されている bpy.ops.object.join() # edge~edge.XXX を1つのオブジェクトに統合(Ctrl+jの操作) edge_obj.name = obj_name #統合したオブジェクトにもとの名前 (obj_name※一番最初にメモってある)を返す bpy.ops.object.mode_set(mode="EDIT") #編集モードに切り替え bpy.ops.mesh.select_all(action='SELECT') #すべて選択 bpy.ops.mesh.remove_doubles() #距離でマージ bpy.ops.mesh.bridge_edge_loops() #辺ループをブリッジ bpy.ops.object.mode_set(mode="OBJECT") #オブジェクトモードに切り替え #★★★ここで一区切り★★★ #使い終わったカーブを消す for ob in bpy.context.scene.objects: #全てのオブジェクトを非選択状態に設定する ob.select_set(False) curve_name = "p_c" #”p_c”をcurve_nameと呼ぶことにする p_c_2 = bpy.data.objects.get(curve_name) #curve_nameを名前に持つオブジェクトをp_c_2とする p_c_2.select_set(True) #p_c_2を選択 bpy.context.view_layer.objects.active = p_c_2 #p_c_2をアクティブにする bpy.ops.object.delete(use_global=False, confirm=False) #p_c_2を削除する #↑の処理を、p_cだけではなく、p_c.001、p_c.002、、にも同様に行っていく。 #★★繰り返し処理Cはここから for i in range(1,slice_n+1): #1から ↑で決めた階層数(slice_n)まで処理を繰り返す curve_name = "p_c." + str(i).zfill(3) #p_c .001、p_c.002、、をcurve_nameとする #zfill (3)は1を001、2を002、、にする関数 p_c_2 = bpy.data.objects.get(curve_name) #curve_nameという名前のオブジェクトをp_c_2とする #↓そんな名前のオブジェクトが存在するか確認する if p_c_2 == None: break #もし存在しなかったら繰り返しを終了する p_c_2.select_set(True) #p_c_2を選択する bpy.context.view_layer.objects.active = p_c_2 #p_c_2をアクティブにする bpy.ops.object.delete(use_global=False, confirm=False) #p_c_2を削除する #★★繰り返し処理Cはここまで #★★★ここで一区切り★★★ #次のためのedgeを作っておく 。(任意の頂点数を持つ棒をつくる。) for ob in bpy.context.scene.objects: #全てのオブジェクトを非選択状態に設定する ob.select_set(False) cut_num = 100 #細分化したい数 verts = [[0, 0, 0], [0, 0, 1]] #頂点0番 (0,0,0)と頂点1番(0,0,1)を定義 edges = [[0,1]] #頂点0番と頂点1番を結んだ辺をedgesとする msh = bpy.data.meshes.new("cubemesh") #Meshデータの宣言 msh.from_pydata(verts, edges, []) #上で定義した頂点 、辺の情報でメッシュを作成 obj = bpy.data.objects.new("edge", msh) # メッシュデータでオブジェクトを作成 bpy.context.scene.collection.objects.link(obj) # シーンにオブジェクトを配置 bpy.data.objects['edge'].select_set(True) #オブジェクト "edge"を選択 bpy.context.view_layer.objects.active = obj #obj (="edge")をアクティブにする bpy.ops.object.mode_set(mode="EDIT") #編集モードに切り替え bpy.ops.mesh.subdivide(number_cuts=cut_num-1) #”edge”をcut_num-1箇所で細分化する(ctrl+E→細分化の操作) bpy.ops.object.mode_set(mode="OBJECT") #オブジェクトモードに切り替え
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

mayaがエラー・ワーニングを吐く時の対処 6 ~どこから来たのかdataStructure~

モデルを2つ以上importした際に出てくるワーニング // Warning: file: D:/hoge.ma line 257023: Structure 'mapManager_stoneFloor' is already defined. Using the original rather than creating a copy. // なんぞこれ?しかもいっぱい出てくるから鬱陶しい。 調べてみる なるほどよくわからん。 とりあえず  - ノード以外で持てるデータ構造  - 一度定義すると、データ構造は編集できない というものであり、 その為データをimportした際 既にシーン内に同名のdataStructureが存在すると 定義済みのdataStructureを再定義しようとすることになるので 先述のようなワーニングが出るという流れかしら。 unknownプラグインほど拡散はしにくいが、 ベースモデルなど使いまわす物に混入していると拡散しやすい。 そもそも、どこからきた? 自セクションでは使用しないが、何かしら必須な物かもしれない。 問い合わせてみたところ 心当たりがない との事。 可能性として考えられるのは・・・ - なにかのプラグインを使用した副産物 - 別のソフトウェアとデータを行き来した際にくっついてきた なんだけれども、ソフトをまたぐ調査は一旦断念。 ※この件についてご存じの方が居たらぜひ教えて頂きたい。 除去 存在するかどうかの確認 import maya.cmds as cmds dataStructure_list = cmds.dataStructure(query=True) if len(dataStructure_list) != 0: print("exists dataStructure!!!") コマンドでの除去 import maya.cmds as cmds cmds.dataStructure( removeAll=True ) 除去した上で、諸々データ上問題が無い事を確認。 どこから入ってきたのか・・・ 想像の域は出ないけれどもここ数年で見かけるようになったので、 マーベラスデザイナー/サブスタンスデザイナー・ペインター あたりのような気もするけれども、調べる元気は今のところ出ないので保留中 ※重ねて、この件についてご存じの方が居たらぜひ教えて頂きたい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Python】ccxtライブラリでFTXから板情報を取得してLineに通知してみた

はじめに 今回はPythonのccxtという複数の仮想通貨取引所のAPI操作が集約されたライブラリを用いて、海外仮想通貨取引所のFTXから板情報を取得して、自分のLineに通知する方法を紹介します。 環境 Python3.9 手順 1.Pythonのインストール Pythonのインストール方法は省きます。検索頂ければ直ぐに見つかるかと思います。 2.ccxtライブラリのインストール 特に他のライブラリのインストールと変わりないですが、過去に記事を書いたので以下でご確認頂ければと思います。 プログラム ccxd.py import ccxt#←CCXTライブラリを呼び出します。変更不要です。 def ftx(): #←CCXTを呼び出します。変更不要です。 ftx = ccxt.ftx({ }) return ftx value = ftx().fetchOrderBook('BTC/USD') #←板情報の入手です。今回は'BTC/USD'を確認します。 #'BTC/USD'の値を変えれば他の仮想通貨の板情報を確認できます。 value['asks'][0][0]#←板情報(asks)の一番上の値を取得するコマンドです。変更不要です。 asks =int(value['asks'][0][0])#←取得した値をint型に変換しています。これをしないとlineに通知できません。変更不要です。 asks_comma= "{:,}".format(asks)#←値にカンマを入れています。この方が見やすいと思いまして。変更不要です。 #↓Lineに通知する箇所です。line_notify_tokenだけご自身で発行をお願いします。それ以外は変更不要です。 import requests from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN addmessage="\r\n"" 現在値:" line_notify_token = '****************************************' line_notify_api = 'https://notify-api.line.me/api/notify' message = addmessage + asks_comma payload = {'message':"\r\n"+ message} headers = {'Authorization': 'Bearer ' + line_notify_token} # 発行したトークン line_notify = requests.post(line_notify_api, data=payload, headers=headers) 最後に いかがでしたでしょうか。 これを定期的に通知させることで投資判断をすることも可能かと思います。 私はLineの通知機能をOFFにして、1時間毎にスマホに通知をしています。 今回はask値を通知させましたが、他にもbid値や先物値なども取得できます。 それを計算させた結果をスマホに通知することも可能です。 ご参考になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Flask+スクレイピングで記事一覧画面を作ろう②

概要 こちらは前回Flask+スクレイピングで記事一覧画面を作ろう①の続きです。 今回は、Flaskの準備を行い、HelloWorldを表示させます。 Flaskの環境を作ろう Macの方はターミナル、Windowsの方はパワーシェル、もしくはコマンドプロンプトで以下のコードを打って仮想環境を作ります。 Anacondaでの仮想環境を作りたい方 # 仮想環境を作ります $ conda create --name flaskenv # 作れたら、仮想環境を適用します $ conda activate flaskenv # Flask, wtforms, requests, BeautifulSoupをインストールします (flaskenv)$ pip install flask wtforms requests beautifulsoup4 2.virtualenvでの仮想環境を作りたい方 # ↓まだvirtualenvをインストールしていない方 $ pip install virtualenv # 仮想環境を作ります $ virtualenv flaskenv # 仮想環境を適用します $ source flaskenv/bin/activate # Flask, wtforms, requests, BeautifulSoupをインストールします (flaskenv)$ pip install flask wtforms requests beautifulsoup4 pyenvを使用した仮想環境も構築できますが、少し複雑になるので以下の記事を参考にすると良いかもしれません。 pyenvとpyenv-virtualenvの自分流使い方 - Qiita HelloWorldを表示しよう 環境の準備ができたので、任意のフォルダにapp.pyを作ってHelloWorldを表示してみましょう。(今回はFlaskScrapingというフォルダを使用します) FlaskScraping/app.py # モジュールのインポート from flask import Flask # Flaskアプリのインスタンスを作成 app = Flask(__name__) # ルーティングの設定 @app.route('/') def index(): return '<h1>Hello World!</h1>' # このコードによって、Flaskがweb上で走ります if __name__ == '__main__': # debug=Trueとすることで、保存するだけで変更が適用されます # エラーも見やすくなります app.run(debug=True) このPythonファイルを実行しましょう。 (flaskenv)FlaskScraping$ python app.py これで、コンソールに http://127.0.0.1:5000/ というURLが表示されるので、これにアクセスしましょう。 Hello World!と表示されていたら成功です! 以上でFlaskの準備もできたので、次回から本格的にアプリを構築していきましょう! ありがとうございました?‍♂️
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む