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

GCP Cloud Functions を GAS トリガーを用いて定期的に実行する

先日、会社で GCP のオンラインセミナーを受講しました。それから折をみては GCP のサーバレス環境である Cloud Functions を触っています。 GCP にデプロイした Cloud Function を定期的かつ自動的に実行させたいことがしばしばあります。いくつか方法がありますが、今回は Google App Script のトリガーを用いてみたいと思います。 Cloud Functions の作成・デプロイ ローカル環境で Cloud Functions を開発 Cloud Functions は Node.js, Java, Go, Python など、いくつかの言語に対応するランタイムがありますが、ここでは私が使い慣れてる Python で HTTP イベントで動く処理を作ってみます。 まずはローカル環境にいくつかライブラリをインストールします。 # pip で functions-framework をインストール $ pip install functions-framework # BeautifulSoupを使うので、別途インストール $ pip install beautifulsoup4 適当なディレクトリを作成し、その中に main.py ファイルを追加します。 $ touch main.py お好きなエディタを使って main.pyを編集します。 今回は Yahoo! Japan のテレビ欄をスクレイピングして、札幌で現在放送している地上波のテレビ番組情報を取得してみます。(注意:スクレイピングはサイトの規約違反になる場合があるので、個人の利用の範囲内で利用するのが無難です。) import urllib.request from bs4 import BeautifulSoup def main(request): # Yahoo! Japan のテレビ欄から現在放送中の番組情報を取得 url = "https://tv.yahoo.co.jp/?a=10" # 開いた html を BeautifulSoup の html.parser で解析 headers = {} request = urllib.request.Request(url=url, headers=headers) response = urllib.request.urlopen(request) html = response.read().decode(response.headers.get_content_charset(), errors='ignore') soup = BeautifulSoup(html, "html.parser") results = { "programs": [] } items = soup.find_all(class_="programOnairListItem") for item in items: # チャンネル番号 channel_num = item.find(class_="programOnairChannelNumber").get_text() # 番組サムネイルURL onair_thumnail_url = item.find(class_="programOnairThumbnail").get('src') # 放送局名 broad_caster = item.find(class_="programOnairBroadcast").get_text() # 放送中の番組名 program_name = item.find(class_="programOnairtProgramText").get_text() obj = { "channel_num": channel_num, "onair_thumnail_url": onair_thumnail_url, "broad_caster": broad_caster, "program_name": program_name, } results['programs'].append(obj) return results コードを保存したら、functions-framework の簡易 Web サーバーを起動して動作確認をしてみます。 # 動作確認 $ functions-framework --target=main --debug * Serving Flask app 'main' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: on * Running on all addresses. WARNING: This is a development server. Do not use it in a production deployment. * Running on http://192.168.100.xx:8080/ (Press CTRL+C to quit) * Restarting with watchdog (fsevents) * Debugger is active! 画面に表示されている Running on 〜 の欄に表示されている URL をコピーし、ブラウザなどからアクセスしてみます。 { "programs": [ { "broad_caster": "HBC\u5317\u6d77\u9053\u653e\u90011", "channel_num": "1", "onair_thumnail_url": "https://tv-pctr.c.yimg.jp/d/tv-image/co/Ae6AQYog8AM/20210903/368x207/0b787d7b785cf383f55eedbe5f155b95.jpg?w=58&h=33&pri=fill&fill=true&fc=f4f5f6&fw=60&fh=33", "program_name": "\u5192\u967a\u5c11\u5e74 \u3042\u3070\u308c\u308b\u541b\u6fc0\u6d41\u5ddd\u4e0b\u308a\u306bSnow Man\u5411\u4e95\u53c2\u6226\uff01\u2606\u30bb\u30b7\u30bf\u30de\u30f3\u7121\u4eba\u5cf6\u5236\u8987" }, { "broad_caster": "NHKE\u30c6\u30ec1\u672d\u5e4c", "channel_num": "2", "onair_thumnail_url": "/img/top/program-channel-noimage.png", "program_name": "\u6cbc\u306b\u30cf\u30de\u3063\u3066\u304d\u3044\u3066\u307f\u305f\u300c\uff45\u30b9\u30dd\u30fc\u30c4\u30e2\u30f3\u30b9\u30c8\u300d" }, { "broad_caster": "NHK\u7dcf\u54081\u30fb\u672d\u5e4c", "channel_num": "3", "onair_thumnail_url": "/img/top/program-channel-noimage.png", "program_name": "\uff2e\uff28\uff2b\u30cb\u30e5\u30fc\u30b9\uff17" }, { "broad_caster": "\u672d\u5e4c\u30c6\u30ec\u30d31", "channel_num": "5", "onair_thumnail_url": "https://tv-pctr.c.yimg.jp/d/tv-image/co/Ae6AQQGC0AM/20210902/600x400/20210902140032535_000.jpg?w=60&h=40&pri=fill&fill=true&fc=f4f5f6&fw=60&fh=40", "program_name": "\u6709\u5409\u30bc\u30df\u25bc\u30ae\u30e3\u30eb\u66fd\u6839\uff36\uff33\u73fe\u5f79\u529b\u58eb\u25bc\u30c7\u30ab\u76db\uff36\uff33\u30b8\u30e3\u30cb\u30fc\u30ba\u6ff1\u7530\u68ee\u672c\u25bc\u6fc0\u8f9b\uff36\uff33\u65e5\u5411\u5742" }, { "broad_caster": "HTB1", "channel_num": "6", "onair_thumnail_url": "https://tv-pctr.c.yimg.jp/d/tv-image/co/Ae6AQoJiAAM/20210901/720x479/bea40ab5436c418caf6b7d75d86793b8.jpg?w=58&h=39&pri=fill&fill=true&fc=f4f5f6&fw=60&fh=39", "program_name": "\uff31\u3055\u307e\u203c\u3000\uff13\u6642\u9593\uff33\uff30" }, { "broad_caster": "TVh1", "channel_num": "7", "onair_thumnail_url": "https://tv-pctr.c.yimg.jp/d/tv-image/pgm/36963/20201001/720x540/7ee60314108c4dc3a5063e3a2f84ec09.jpg?w=60&h=45&pri=fill&fill=true&fc=f4f5f6&fw=60&fh=45", "program_name": "\uff39\uff2f\uff35\u306f\u4f55\u3057\u306b\u65e5\u672c\u3078\uff1f\u2605\u5357\u30b9\u30fc\u30c0\u30f3\u4e94\u8f2a\u4ee3\u8868\u306e\u6fc0\u95d8\uff06\u7d50\u5a5a\u5f0f\u3067\u30b5\u30d7\u30e9\u30a4\u30ba\u5927\u4f5c\u6226" }, { "broad_caster": "\u5317\u6d77\u9053\u6587\u5316\u653e\u90011", "channel_num": "8", "onair_thumnail_url": "https://tv-pctr.c.yimg.jp/d/tv-image/co/Ae6AQgSsUAM/20210831/640x426/ee4903b40bf54faaa7ce7e57601b935f.jpg?w=58&h=39&pri=fill&fill=true&fc=f4f5f6&fw=60&fh=39", "program_name": "\u75db\u5feb\uff34\uff36\u3000\u30b9\u30ab\u30c3\u3068\u30b8\u30e3\u30d1\u30f3\u82b8\u80fd\u4eba\u306e\u4eba\u751f\u5909\u3048\u305f\u5927\u4e8b\u4ef6\uff01\u5b9f\u8a71\u3092\u30c9\u30e9\u30de\u5316\uff12\u6642\u9593\uff33\uff30" } ] } 日本語文字列が Unicode エスケープされてるのが気になりますが、ひとまず結果は戻ってきました。 requirements.txt の作成 作成したコードはスクレイピングした html 情報を BeautifulSoup4 ライブラリを使って解析しています。ただ BeautifulSoup4 は Python3 の標準外のライブラリのため、Cloud Functions の環境にデプロイしてもライブラリが存在せず動作しない可能性があります。 このライブラリを Cloud Functions の環境に導入するため requiments.txt を用意します。 main.py と同じディレクトリに requirements.txt を追加します。 $ touch requirements.txt $ echo beautifulsoup4 > requirements.txt デプロイ ローカル環境での動作確認・テストが済んだら GCP の Cloud Functions 環境にデプロイします。 今回は gcloud コマンドを使ってデプロイを行ってみます。 $ gcloud functions deploy tv_program --entry-point main --runtime python38 --trigger-http --project --project [gcp_project_name] Allow unauthenticated invocations of new function [tv_program]? (y/N)? y Deploying function (may take a while - up to 2 minutes)...⠛ For Cloud Build Stackdriver Logs, visit: https://〜 Deploying function (may take a while - up to 2 minutes)...⠹ しばらく待つと、画面に Updates are available for some Cloud SDK components. To install them, please run: $ gcloud components update このような文字が出てきます。 これでGCPの指定プロジェクト上に、Cloud Functions コードのデプロイができました。 Google App Script の作成 Google SpreadSheet のスクリプト処理で Cloud Functions の処理を呼び出す 次に、GCP から一旦離れて、新規のGoogle SpreadSheet を作成します。 [ツール] > [スクリプト エディタ] と選択してスクリプトエディタを開き、先ほどデプロイした GCP の Cloud Functions を呼び出す処理を書きます。 以下のスクリプトを設定します。 function getTvProgram() { var url = "[デプロイした Cloud Functions の URL]"; var res = UrlFetchApp.fetch(url).getContentText(); var json = JSON.parse(res); return json; } function updateTvProgram() { var spreadSheetById = SpreadsheetApp.openById('[スプレッドシートのid]'); var json = getTvProgram(); var date = new Date(); var nowTime = Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy-MM-dd: HH:mm:ss'); var targetCell = spreadSheetById.getRange('B1'); targetCell.setValue(nowTime); var programs = json['programs']; // 番組情報欄を消す var targetCells = spreadSheetById.getRange('A3:D20'); targetCells.clearContent(); // 番組情報を取得 var initRow = 3; for(var i=0; i<programs.length; i++) { // JSONから情報取得 var channel_num = programs[i]['channel_num']; var broad_caster = programs[i]['broad_caster']; var onair_thumnail_url = programs[i]['onair_thumnail_url']; var program_name = programs[i]['program_name']; // セルに情報を書き込む var targetRowIdx = initRow + i; spreadSheetById.getActiveSheet().getRange(targetRowIdx, 1).setValue(channel_num); spreadSheetById.getActiveSheet().getRange(targetRowIdx, 2).setValue(broad_caster); if(onair_thumnail_url != "/img/top/program-channel-noimage.png") { image_func = '=IMAGE("' +onair_thumnail_url+ '", 4, 32, 60)'; spreadSheetById.getActiveSheet().getRange(targetRowIdx, 3).setValue(image_func); } spreadSheetById.getActiveSheet().getRange(targetRowIdx, 4).setValue(program_name); } } スクリプトの説明です。getTvProgram 関数で Cloud Functions のトリガーURLにアクセスして TV 番組情報を取得しています。 updateTvProgram 関数の方で、getTvProgram 関数から得られた TV 番組情報をもとにして、Google SpreadSheet のシートを書き換える処理を行ってます。 スクリプトエディタの実行部から updateTvProgram の関数を選択して実行すると、スクリプトをどのアカウントから操作するか、許可を求められるので、許可の設定を行います。 設定を行って処理が完了すると、Google SpreadSheet の内容がこのように変わります。 Google App Script にトリガーを設定 Google SpreadSheet のスクリプトから Cloud Functions を呼び出せることが確認できたら、処理を定期的に動かすためにトリガーを設定します。 実行する関数を選択 : updateTvProgram イベントのソースを選択 : 時間主導型 時間ベースのトリガーのタイプを選択 : 分ベースのタイマー 時間の感覚を選択(分) : 適当に選択 この内容でトリガー設定を保存することで、設定した時間(分)ごとにトリガーが動きだします。 トリガーに関連づけた関数で Cloud Functions が呼び出され、定期的にシート内容を書き変えることができます。Google SpreadSheet はクラウドの環境に存在しているので、PC でシートを開いていなくてもトリガーは実行されつづけます。 これにて Google App Script を使って Cloud Functions の処理を定期的に実行できるようになりました。(単に Cloud Functions を定期実行するだけであれば、Cloud Function の呼び出し関数だけをトリガーに設定すればいいです) その他 ここまでの手順では処理を動かすことを優先したため、Cloud Functions に関する権限設定は特に行ってません。そのため Cloud Functions の処理を動かすエントリーポイントの URL がわかれば誰でも処理が実行できてしまう状態です。 これはあまりよろしくないので、Cloud Functions になにかしらのセキュリティ設定を行う必要がありますが、そのあたりについては別の記事にまとめます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ABC202 C - Made Up を解いてみた

いつもの通り i, j をそれぞれ for でネストして全探索したら TLE で落ちてしまう。とりあえずサンプルを眺める for 文で B[C[i]-1] について i で回してみよう。 その時にB[C[i]-1] と同じ値が 配列 A の中に何個あるのか数えれば良さそう。 ってことは事前に辞書で A について整理しておけば解決すると思った。 MadeUp.py N = int(input()) A = list(map(int,input().split())) B = list(map(int,input().split())) C = list(map(int,input().split())) #A の中に何の要素が何個ずつ入っているのか管理 dic = {} for i in range(N): if A[i] not in dic: dic[A[i]] = 0 dic[A[i]] += 1 score = 0 for i in range(N): try: score += dic[B[C[i]-1]]#該当したら、その個数を積み上げる except: pass# B[C[i]-1] が辞書内に存在しないと言われたら pass する print(score) atcoder problem 灰色〇で半分くらいのレベルだったら C 問題でも何とか。。 ちょっとずつレベルを上げていきたいところですね。 おまけ 間違っても以下のようにしない方がいいと思います。 MadUp_TLE.py N = int(input()) A = list(map(str,input().split())) B = list(map(int,input().split())) C = list(map(int,input().split())) A = "".join(A) score = 0 #以下のように O(N^2) となるので TLE となります。 for i in range(N): #=> N score += A.count(str(B[(C[i])-1])) # => N : # count は都度 A の中を要素数(N) だけ探索してカウントするため # 計算量は N と認識されます。 print(score)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WebAPIでpythonコードを実行できるシステムを作った話

なぜ作ったのか 時々バッチ処理やスレイピングなど長時間動作させたいプログラムを書くことがあります もちろんローカルで実行すれば良いのですが 重たい処理であったり長い時間実行する必要がある場合、PCに負荷がかかるのを避けるためです 作ったもの WebAPIのBodyにpythonのコードを書いてPOSTするとが実行されて結果が返されます 技術スタック 言語 python フレームワーク django デプロイ先 Heroku コード Djangoで作っているので、url.pyとview.pyのみ載せます Djangoに関する情報は探せばいっぱい出てくると思うのでそちらを参照ください url.py path('wakeup/',views.wakeup ,name='wakeup'), path('api-exec/',views.api_exec ,name='api-exec'), path('api-exec-async/',views.api_exec_async ,name='api-exec-async'), path('api-exec-async-log/',views.api_exec_async_log ,name='api-exec-async-log'), view.py api_exec_async_data = {} @csrf_exempt def api_exec(request): """ POSTされたPythonのコードを同期実行します """ try: data = {} code = request.body.decode('utf-8') # exec(code, data) except Exception as e: print(traceback.format_exc()) return HttpResponse(traceback.format_exc(), status=400) exec(code, data) if 'exec_result' in data.keys(): return HttpResponse(data['exec_result']) else: return HttpResponse('') @csrf_exempt def api_exec_async(request): """ POSTされたPythonのコードを非同期実行します """ try: code = request.body.decode('utf-8') except Exception as e: print(traceback.format_exc()) return HttpResponse(traceback.format_exc(), status=400) t1 = threading.Thread(target=exec, args=([code,api_exec_async_data])) t1.start() return HttpResponse('OK') def api_exec_async_log(request): """ 非同期実行のログを取得します """ if 'exec_result' in api_exec_async_data.keys(): return HttpResponse(api_exec_async_data['exec_result']) else: return HttpResponse('') def wakeup(request): """ djangoの起動を維持します """ return HttpResponse("") 使い方 api-exec pythonのコードが同期的に実行され、結果が返ります api_exec_async pythonのコードが非同期的に実行されます 結果取得は難しいので、DBを用意するなどしてそこにデータを投入するようにします api_exec_async_log 非同期実行時のログを取得します 実際に使ってみる 同期実行  exec_resultに結果を入れると、レスポンスとして実行結果が返ります また、printでサーバサイドにログとして出力されます 非同期実行 exec_resultに結果・ログを入れると「api_exec_async_log」で結果・ログが取得できるようになります ただ、消滅してしまう可能性もあるため、実行中フラグなどに使用するのが良いと思います 非同期実行時のログ取得 非同期実行時にexec_resultに入っている値を取得できます 非同期実行時の実行結果の保存 「非同期実行時は結果の取得が困難なので、DBを用意してデータを投入します」と書きましたが RealtimeDatabaseのRestApiがおすすめです(コレについては別記事を書くかもしれません・・・?) 何気なく使っていますが、importも使用できます もちろん、環境に対応するライブラリがあることが条件になります 実行WebAPI(RealtimeDatabaseのRestApiを使用してデータを保存) RealtimeDatabaseの中身 この記事を書いていて思ったこと pythonコードを実行できるWebAPI 「+そのコードを保存出来る」という機能を実装すれば AWS Lambda的なサーバーレスコンピューティングサービスが出来るのでは?!と思いました 作れたら、また記事を書こうかと思います まとめ 外部から入力されたコードがかんたんに実行できるところが さすが動的言語だなぁと思いました それくらいですかね・・・? 書き忘れていましたが、Herokuの無料枠では起動から30分なにもアクセスがないとスリープモードに入ります なので、wakeupというAPIを用意したのですが・・・ 重たい処理を動かす際はfor文のなかにwakeupAPIを叩くように工夫する必要があったります 以上です
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Pythonで日本語文の中の生物の学名を抜き出す

(追記)コメント欄で以下よりシンプルな書き方を教えていただきました。 モチベーション 生物の学名は斜体で書くという決まりがあります。Wordに文章を打ち込んでいる時に、いちいち学名を手作業で斜体にするのが面倒なので、自動化したいです。そのための第一歩としてPythonで学名を抜き出してみます。 ちなみにPython 学名で検索するとニシキヘビ(Python)の情報が出てきます。 学名を抜き出す 日本語文の中に半角英字で学名が書かれていることを想定。例文はWikipediaの「クラミドモナス」より取りました。 Python text = "クラミドモナス(Chlamydomonas)は緑藻綱クラミドモナス目(もしくはオオヒゲマワリ目)に属する単細胞の鞭毛虫からなる属である。"\ "500種以上が知られているが、単にクラミドモナスと言えば、モデル生物として盛んに利用されている"\ "コナミドリムシ(Chlamydomonas reinhardtii)を指すことが多い。"\ "C. reinhardtii は分子生物学、特に鞭毛の運動や葉緑体の動力学、発生生物学、遺伝学の研究のモデル生物である。"\ "チャンネルロドプシンのような、光感受性のイオンチャネルを持っていることは、クラミドモナスの特筆すべき性質の一つである。"\ "「ウォーターメロン・スノー」として知られる、雪山がピンク色(あるいは赤色)に染まる現象は、同属の C. nivalis のしわざである。" 文章の中に出てくる学名には3パターンあります(上の文章はすべてのパターンを網羅しています)。 1. 属名のみ 例:Chlamydomonas 2. 属名+種小名 例:Chlamydomonas reinhardtii 3. 属名の頭文字+種小名 例:C. reinhardtii 属名の頭文字は大文字、種小名はすべて小文字です。 英語など、ラテンアルファベットで記述される言語の文章から学名を抜き出すのはそれなりに面倒そうですが、日本語文からなら正規表現で半角英字を探せばできそうです(まさか全角で学名を書く生物学者はいないでしょう)。ということで、やりました。正規表現弱者なので、もっとエレガントな書き方があるよという人は教えてください。 Python import re result = re.findall(r"[A-Z][a-z]+ [a-z]+|[A-Z][a-z]+|[A-Z]\. [a-z]+", text) print(result) とりあえず全部抜き出せたようです。 正規表現の|(OR)前後の順番を変えるとうまくいきませんでした。 Python result = re.findall(r" A | B | C ", text) となっている時に、A, B, Cの順番で探すものと思われます。 上のコードでは、「属名+種小名|属名のみ|属名の頭文字+種小名」の順番で探しています。「属名のみ|属名+種小名|属名の頭文字+種小名」とすると、「属名+種小名」がうまく探せませんでした。 参考 論文での動植物の学名の記載方法 クラミドモナス 【Python】文字列からアルファベットのみを抽出する方法 複数の文字列のいずれかにマッチするパターンを記述する 正規表現でスペースを記述する方法+Pythonサンプルコード
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Python 入門2 (データー構造)

はじめに 今回の記事では、Pythonの基礎的な文法について、Udemyの講座にて学習した内容を記載する。 主に下記の講座にて勉強致しました。(Udemyの講師から許可を頂いています) 現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイル セクション4:「データー構造」 目次 1.リスト型 2.リストの操作 3.リストのメソッド 4.リストのコピー 5.リストの使い所 6.タプル型 7.タプルのアンパッキング 8.タプルの使い所 9.辞書型 10.辞書型のメソッド 11.辞書のコピー 12.辞書の使い所 13.集合型 14.集合のメソッド 15.集合の使い所 1-リスト型 リストを宣言 この章では、以下のリスト型変数lを用いて説明する l = [1,20,4,50,2,1,2] l [1, 20, 4, 50, 2, 1, 2] リスト先頭を表示 l[0] 1 リスト最後尾を表示 l[-1] 2 リストの特定の範囲を指定 l[0:2] [1, 20] l[:2] [1, 20] l[2:5] [4, 50, 2] l[2:] [4, 50, 2, 1, 2] l[:] [1, 20, 4, 50, 2, 1, 2] リストの長さを表示 len(l) 7 変数の型を確認すると、リスト型であることを確認できる print(type(l)) <class 'list'> 範囲外アクセスするとエラーが発生してしまう l[100] IndexError Traceback (most recent call last) <ipython-input-14-e2a0c2623844> in () ----> 1 l[100] IndexError: list index out of range リストの中身を一つ飛ばしで取得する l[::2] [1, 4, 2, 2] リストの中身を逆順で表現する あまり使用しない l[::-1] [1, 4, 2, 2] list型に変換 list('abcdefg') ['a', 'b', 'c', 'd', 'e', 'f', 'g'] 2-リストの操作 ここではリストsを用いて説明する s=['a','b','c','d','e','f','g'] s ['a', 'b', 'c', 'd', 'e', 'f', 'g'] 先頭文字列の書き換え s[0] 'a' s[0] = 'X' s ['X', 'b', 'c', 'd', 'e', 'f', 'g'] スライスにより指定した範囲の書き換え s[2:5] ['c', 'd', 'e'] s[2:5] = ['C', 'D', 'E'] s[2:5] ['C', 'D', 'E'] s ['X', 'b', 'C', 'D', 'E', 'f', 'g'] 指定した範囲を空リストにする s[2:5] = [] s ['X', 'b', 'f', 'g'] 全体を空リストにする s[:] ['X', 'b', 'f', 'g'] s[:] = [] s [] ここからはリストnを用いて説明する n = [1,2,3,4,5,6,7,8,9,10] n [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] append : リストの最後尾に要素を追加 n.append(100) n [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100] insert : 指定したリスト番号に要素を追加(挿入) n.insert(0,200) n [200, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100] pop : リストの最後尾の要素を取り出す n.pop() 100 n [200, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] pop : 指定した要素を取り出す n.pop(0) 200 n [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] del : 指定した要素を削除する del n[0] n [2, 3, 4, 5, 6, 7, 8, 9, 10] del : 要素を全削除する 削除した後に確認しても警告メッセージが出力されるのみである del n n Traceback (most recent call last): File "", line 1, in NameError: name 'n' is not defined remove : 指定した要素を取り出す(ここでは2を取り出す) n = [1,2,3,2,2,3] n.remove(2) n [1, 3, 2, 2, 3] n.remove(2) n.remove(2) n [1, 3, 3] n.remove(2) Traceback (most recent call last): File "", line 1, in ValueError: list.remove(x): x not in list リストを結合 a = [1,2,3,4,5] b = [6,7,8,9,10] x = a + b x [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] aそのものにbの要素を追加 a += b a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] リストを結合(別解) x = [1,2,3,4,5] y = [6,7,8,9,10] x.extend(y) x [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 3-リストのメソッド index : リストから引数で指定した要素のインデックス(0始まり)を返す 以下は 3 のインデックスを出力するコードである r = [1, 2, 3, 4, 5, 1, 2, 3] print(r.index(3)) 実行結果:2 また、以下はインデックス3から後ろの要素にかけて要素が3であるインデックスを探す例である print(r.index(3, 3)) 実行結果:7 count : 引数の要素と一致する回数を返す print(r.count(3)) 実行結果:2 sort : リストの中身をソートする(reverse = True で逆順)となる reverese : リストの中身の昇順および降順を逆転させる r.sort() print(r) r.sort(reverse=True) print(r) r.reverse() print(r) 実行結果: [1, 1, 2, 2, 3, 3, 4, 5] [5, 4, 3, 3, 2, 2, 1, 1] [1, 1, 2, 2, 3, 3, 4, 5] 文字列をsplit関数を使用して空白文字を基準にリストで分ける s = 'My name is Mike.' to_split = s.split(' ') print(to_split) 実行結果:['My', 'name', 'is', 'Mike.'] join関数を利用してもとに戻す x = ' '.join(to_split) print(x) 実行結果:My name is Mike. 4-リストのコピー リストのコピーは値渡しではなく参照渡しである為、要注意 i = [1, 2, 3, 4, 5] j = i j[0] = 100 print("j = ", j) print("i = ", i) 実行結果: j = [100, 2, 3, 4, 5] i = [100, 2, 3, 4, 5] ※ j[0]の値だけでなく、i[0]の値も変更されてしまう 値渡しに変更する方法1. copy x = [1, 2, 3, 4, 5] y = x.copy() x[0] = 100 print("x = ", x) print("y = ", y) 値渡しを変更する方法2. : x = [1, 2, 3, 4, 5] y = x[:] x[0] = 100 print("x = ", x) print("y = ", y) 実行結果:両方とも同じ結果を返す x = [100, 2, 3, 4, 5] y = [1, 2, 3, 4, 5] →x[0]の値のみ書き換わっていることが確認できる 値渡しと参照渡しの違い 値渡しの場合は、値を渡しているのみでアドレス値は異なる X = 20 Y = X Y = 5 print(id(X)) print(id(Y)) print(X, Y) 実行結果: 140724313236464 140724313235984 20 5 参照渡しの場合は、アドレス値ごとコピーする a = ['a', 'b'] b = a print(id(a)) print(id(b)) print(a, b) 実行結果 2071094775624 2071094775624 ['a', 'b'] ['a', 'b'] 5-リストの使い所 リストを用いて論理演算を実行 >>> seat = [] >>> min = 0 >>> max = 5 >>> min <= len(seat) < max True >>> seat.append('p') >>> seat.append('p') >>> min <= len(seat) < max True >>> seat.append('p') >>> seat.append('p') >>> min <= len(seat) < max True >>> seat.append('p') >>> min <= len(seat) < max False >>> seat.pop() 'p' >>> min <= len(seat) < max True 6-タプル型 タプルtupleはリストと異なり、値を書き換えることはできない ROMなど値を書き換えたくないときに使用 >>> t = (1,2,3,4,1,2) >>> t[0] = 100 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> t[0] 1 >>> t[-1] 2 >>> t.count(1) 2 タプルは書き換えることはできないが、タプルの中にリストを宣言することはできる >>> t = ([1,2,3],[4,5,6]) >>> t ([1, 2, 3], [4, 5, 6]) >>> t[0] = 100 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> t[0][0] = 100 >>> t ([100, 2, 3], [4, 5, 6]) ()を外して宣言してもタプルとなる >>> t= 1,2,3 >>> t (1, 2, 3) >>> type(t) <class 'tuple'> また、「,」をつけた状態だと、要素数1個でもタプルとなる ただし、int型の変数を宣言する場合と「,」の違いでしか違いがないためバグの原因になりやすいので要注意 >>> t = 1, >>> t (1,) >>> type(t) <class 'tuple'> >>> t = 1 >>> t 1 >>> type(t) <class 'int'> タプルの中身が空だとtuple型だが、「,」なしで1個だけ要素を入れるとint型になってしまうので要注意 >>> t = () >>> t () >>> type(t) <class 'tuple'> >>> t = (1) >>> t 1 >>> type(t) <class 'int'> 文字列の場合も同様 >>> t = 'test' >>> type(t) <class 'str'> >>> t = ('test',) >>> type(t) <class 'tuple'> 良く起こりえるミス tをint型として宣言していたつもりが、間違えてtupleで宣言してしまい演算エラーが発生する >>> t = 1, >>> t = t +100 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate tuple (not "int") to tuple タプルの演算 →タプルには「,」を入れることを忘れないこと >>> t = (1,2,3)+(4,5,6) >>> t (1, 2, 3, 4, 5, 6) >>> t = (1)+(4,5,6) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'int' and 'tuple' >>> t = (1,)+(4,5,6) >>> t (1, 4, 5, 6) 7-タプルのアンパッキング タプルのアンパッキング : 変数の宣言で使われる技術 num_tuple = (10, 20) x, y = num_tuple print(x, y) min, max = 0, 100 print(min, max) 実行結果: 10 20 0 100 ※変数の数が多すぎると可読性が下がるので注意 タプルのアンパッキングは要素の入れ替えでも役に立つ 通常のプログラミングなら下記の通りでよく習うが。。。 i, j = 10, 20 tmp = i i = j j = tmp print(i, j) タプルのアンパッキングを使用すると下記のコードとなる i, j = 10, 20 i, j = j, i print(i, j) 8-タプルの使い所 タプルは選択肢の用意としてよく使われる タプルは値を書き換えたくないときによく使われる 9-辞書型 辞書型(dict):変数と値を関連付け >>> d = {'x': 10,'y': 20} >>> d {'x': 10, 'y': 20} >>> type(d) <class 'dict'> 配列に辞書で指定した文字列を指定したら、値を得ることができる >>> d['x'] 10 >>> d['y'] 20 指定した辞書に値を代入することもできる >>> d['x'] = 100 >>> d {'x': 100, 'y': 20} 値として文字列を代入することもできる >>> d['x'] = 'XXXX' >>> d {'x': 'XXXX', 'y': 20} 辞書を作成した後も値を追加することもできる >>> d['z'] = 200 >>> d {'x': 'XXXX', 'y': 20, 'z': 200} 配列に文字列だけでなく、値そのものを指定することもできる >>> d[1] = 10000 >>> d {'x': 'XXXX', 'y': 20, 'z': 200, 1: 10000} dict型作成別解1 >>> dict(a=10, b=20) {'a': 10, 'b': 20} dict型作成別解2 >>> dict([('a',10), ('b', 20)]) {'a': 10, 'b': 20} ※dictを作成する方法はアプリ開発時に場面ごとに異なる 10-辞書型のメソッド キー:値 それぞれを個別で使用する >>> d = {'x': 10,'y': 20} >>> d {'x': 10, 'y': 20} keysのみを取得 >>> d.keys() dict_keys(['x', 'y']) valuesのみを取得 >>> d.values() dict_values([10, 20]) dict型で宣言した構造をアップデートさせる方法 アップデート用に新たなdict変数を用意(d2) 既存のdict変数(=d)を新たなdict変数(d2)でアップデートさせる >>> d2 = {'x': 1000,'j': 500} >>> d2 {'x': 1000, 'j': 500} >>> d.update(d2) >>> d {'x': 1000, 'y': 20, 'j': 500} 値を取り出すには、キー値を配列番号として取り出すだけでなく、getメソッドを用いて取り出す方法もある >>> d['x'] 1000 >>> d.get('x') 1000 両者の違いがわかりにくいが、キー値がdict変数に存在しない場合に違いが生じる配列番号で指定する方は、エラーが出力されるが、getメソッドの場合は出力結果としてNoneが返される >>> d['z'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'z' >>> r = d.get('z') >>> r >>> type(r) <class 'NoneType'> pop関数で値を取り出す >>> d {'x': 1000, 'y': 20, 'j': 500} >>> d.pop('x') 1000 >>> d {'y': 20, 'j': 500} del関数で値を削除する >>> del d['y'] >>> d {'j': 500} del関数でdict変数そのものを削除する >>> del d >>> d Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'd' is not defined clear関数を使用した場合はdel関数とは異なりdict変数を削除するのではなく、dict変数を空にする >>> d = {'a':100, 'b':200} >>> d.clear() >>> d {} in関数を用いて、キー値がdict変数に存在するかどうかを2値分類で確認することができる >>> d = {'a':100, 'b':200} >>> d {'a': 100, 'b': 200} >>> 'a' in d True >>> 'j' in d False 11-辞書のコピー dict変数も、代入でコピーしようとすると参照渡しとなってしまう。 以下の例では、yの値を書き換えると、xの値も書き換わってしまう。 >>> x = {'a': 1} >>> y = x >>> y['a'] = 1000 >>> print(x) {'a': 1000} >>> print(y) {'a': 1000} dict変数の参照渡しを避けるにはcopy関数を使用する yの値を書き換えても、xの値は書き換わっていないことが確認できる >>> x = {'a': 1} >>> y = x.copy() >>> y['a'] = 1000 >>> print(x) {'a': 1} >>> print(y) {'a': 1000} 12-辞書の使い所 ハッシュテーブルでよく使われる 13-集合型 集合型:重複している値は削除される >>> a = {1,2,2,3,4,4,4,5,6,6} >>> a {1, 2, 3, 4, 5, 6} >>> type(a) <class 'set'> >>> b = {2,3,3,6,7} >>> b {2, 3, 6, 7} 論理演算 - 差集合 >>> a - b {1, 4, 5} >>> b - a {7} 積集合 >>> a & b {2, 3, 6} 和集合 >>> a | b {1, 2, 3, 4, 5, 6, 7} 排他的論理和 >>> a ^ b {1, 4, 5, 7} ※「+」記号は使用できない >>> a + b Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'set' and 'set' 14-集合のメソッド 集合型は 配列番号では指定ができない >>> s = {1, 2, 3, 4, 5} >>> s {1, 2, 3, 4, 5} >>> s[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'set' object is not subscriptable add関数で要素を追加する 集合型なので同じ値を繰り返し追加しても意味なし >>> s.add(6) >>> s {1, 2, 3, 4, 5, 6} >>> s.add(6) >>> s {1, 2, 3, 4, 5, 6} remove関数で要素を取り除く ※集合にない値を指定するとエラーとなる >>> s.remove(6) >>> s {1, 2, 3, 4, 5} >>> s.remove(6) Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 6 clear関数で集合の中身を空にする >>> s.clear() >>> s set() 空の場合「set()」と表示されるのは、dict型と区別するためである >>> a = {} >>> type(a) <class 'dict'> >>> a {} 15-集合の使い所 リストから重複を削除し、種類の一覧を表示するのに使用される 論理演算を使用し、共通項を洗い出すときに使用される 参考文献 現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイル セクション4:「データー構造」
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Lost connection to MySQL server during query

Flask-SQLAlchemyでMySQLを使っていてハマった事象について。 発生事象 Flaskアプリケーションを起動して長時間(8時間くらい?)経過後にブラウザでアクセスするとInternal Server Error。エラーログは下記の内容。 sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') Internal Server Error発生後、ブラウザで再読み込みするとエラーは解消される。 が、さらに長時間経過すると再び同様のエラーが発生。 環境 Python 3.9.5 MySQL 5.7.34 Flask 2.0.0 Flask-SQLAlchemy 2.4.4 PyMySQL 1.0.2 原因と対策 どうやら長時間経過するとコネクションプールが死んでしまう模様。 これを解消するにはDBアクセスの前にpingを飛ばしてやる、すなわち SELECT 1 のような特に何もしないSQLを投げてコネクションプールを復活させてやればOK。 この方法はSQLAlchemyの機能として提供されており、デフォルトでは使用しない設定となっている。 create_engine の引数に pool_pre_ping=True を渡せとのことだったが、A Minimal Applicationをどう改修したらいいものやら、いろいろ試した結果以下の方法に落ち着いた。 flask_app.py(抜粋) app = Flask(__name__) app.config['SQLALCHEMY_ENGINE_OPTIONS'] = { 'pool_pre_ping': True } とりあえず長時間経過してもエラーは出なくなった。 わからないこと MySQL以外のDBMSでは発生しないのか?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

djangoのMiddleWareに頼らなく、自作でSessionのキーと値をブラウザに保存しましょう!

Djangoは独自のsession処理機能が実装されていますが、自分なりのsessionを作ることももちろんできます。 例えば: このように、好きなNameを設定し、あるいはいくつのcookiesをまとめてブラウザに保存することで、ブラウザから二回目のrequestが来た時、必要なデータも簡単に手に入れることができます。 Template 簡便のため、form tagを使ってLogin画面を想像してください。 MiddleWare class Cust_session(MiddlewareMixin): def process_request(self, request): request.my_session = {'my_session_id':'', 'my_session_value':''} request.name = '' def process_response(self, request, response): my_session_value = request.my_session.get('my_session_value') print(my_session_value) hl = hashlib.md5() hl.update(request.name.encode('utf-8')) re_username = hl.hexdigest() request.my_session['my_session_id'] = re_username print(request.my_session) response.set_cookie('my_session_id_plus',request.my_session['my_session_id']) return response Views層 def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') user_obj = True if username == 'A' and 'password' == 123 else False if user_obj: request.my_session['my_session_value'] = {'name':username, 'password':password} request.name = username return HttpResponse('ok') return render(request, 'login.html', locals()) process_requestで設定されたrequest.my_sessionはViewsに渡し、Viewsのlogin関数はrequest.my_sessionのmy_session_valueの値を与える。 process_responseはViewsからのrequest.my_sessionをチェックし、my_session_idがないため、Viewsから与えられたrequest.nameを暗号化し、ブラウザで保存するmy_session_id_plusのvalueとなります。 単純にブラウザで保存されているcookiesのカスタマイズに過ぎないため、ご了承ください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Python学習日記 ~文字列型に関連するメソッドについて~

ということで、python学習開始2日目です。 学んだことは自分で文字に起こして忘れないよう、 知識定着できるよう適宜まとめていきたいと思います。 まず、pythonでは、 オブジェクト.メソッド()  として、関数を示すことがわかりました。いままでやってきたPHPの時とはちがうなあ! JSと近いイメージだなと思いました。(素人感想すみません、、) 以下は本日学習した、文字列に関連する関数とユースケースです。 文字列の複製 fruit_10 = 'fruit' * 10 print(fruit_10) →fruitfruitfruitfruitfruitfruitfruitfruitfruitfruitfruitfruit 文字列の連結 new_fruit = 'apple' + 'banana' print(new_fruit) →applebanana 特定のインデックスの文字のみ抽出 fruit = 'fruit' print(fruit[2]) →u ※f(0) r(1) u(2) i(3) t(4) count 指定の文字列が何個あるか msg = 'ABCDEABC' print(msg.count('ABC')) msg内に’ABC’は2個あるから、2を返す startswith 指定の文字列から始まっているかいないか msg = 'ABCDEABC' print(msg.startswith('ABCD')) msgは’ABCD’で始まっているので、Trueを返す 違う場合は、Falseを返す endtswith 指定の文字列で終わっているかいないか msg = 'ABCDEABC' print(msg.endswith('ABC')) msgは’ABC’で終わっているので、Trueを返す 違う場合は、Falseを返す strip(両端) rstrip(右端) lstrip(左端) msg = 'ABCDEABC' print(msg.strip('CBA')) 両端から、’CBA’それぞれと一致した文字列を削除する 上記の場合は、両端にA/B/Cがあるので、DEを返す。 例えば msg = 'ABCDEABC' print(msg.strip('CA')) とすると、左端の場合は、まずAを削除。 次のBはstripで指定していないのでそこで削除終了。 右はCを削除。次のBはないので削除終了。BCDEABを返す。 rstripは右端のみ。lstripは左端のみを返す。 upper lower swapcase 大文字・小文字を変換する msg = 'abcABC' msg_u = msg.upper() #大文字 msg_l = msg.lower() #小文字 msg_s = msg.swapcase() #大文字と小文字を変換する ・upper:すべての文字列を大文字にする(msg_u = ABCABC) ・lower:すべての文字列を小文字にする (msg_l = abcabc) ・swapcase:すべての文字列の大文字と小文字を入れ替える (ABCabc) replace 文字列の置換 msg = 'ABCDEABC' msg_r = msg.replace('ABC', 'FFF') 第1引数の文字列を第2引数の文字列に置換する(msg_r = FFFDEFFF) 第3引数があるとき msg = 'ABCDEABC' msg_r = msg.replace('ABC', 'FFF', 1) #変換 第三引数は左からその順番のものだけ変換 第3引数には数値を入れる。左から順に見てn番目の文字列のみ置換する 上記の場合は、msg_r = FFFDEABC capitalize 一文字目のみ大文字に変換 msg = 'hello World' print(msg.capitalize()) 上記の場合は、Hello worldを返す。 ※大文字だったWは一文字目ではないので小文字に変換 文字列の一部取り出し msg = 'hello my name is Taro' print(msg[:7]) print(msg[7:]) print(msg[1:7]) print(msg[1:7:2]) 上から順に、 hello m(indexで数えて7番目まで) y name is Taro(indexで数えて7番目よりあと) ello m(indexで数えて1番目から7番目まで) el(indexで数えて1番目から7番目までを2文字飛ばしで’e’’l’’ ’) ※第3引数はn文字飛ばしで取り出しを行う。 islower と isupper 大文字小文字の判別 ・islower すべて小文字ならTrue 一文字でも小文字でないならFalse ・isupper すべて大文字ならTrue 一文字でも大文字でないならFalse msg = 'apple' print(msg.islower()) #すべて小文字なのでTrue print(msg.isupper()) #すべて大文字ではないのでFalse find rfind index rindex 文字列のある場所を返す msg = 'ABCDEABC' print(msg.find('ABC')) print(msg.rfind('ABC')) print(msg.index('ABC')) print(msg.rindex('ABC')) 上から順に、 0(indexで0番目にあるため) 5(indexで5番目にあるため) 0(indexで0番目にあるため) 5(indexで5番目にあるため) ※findとindexの違いは、指定の文字列が見つからなかったとき find:見つからなかったら、-1を返す index:見つからなかったら、エラーとなる 所感 今までPHPを少し学んでいたこともあって、そんなに抵抗なくメソッドの知識が入ってきている実感があります。さっさと知識身に着けてアプリ作ってみて10月の入社まで引き続き頑張ります。 つたない文章でしたが、お読みいただいてありがとうございました。 ※encodeとformatは落ち着いたら別の機会にまとめようと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【pandas】2つのテーブルを結合し、合計と平均を求める

はじめに Python初学者です。 GoogleColaboratoryにて日々勉強中です。 今回はpandasのメソッドの理解を深めるため、自身で例題を作り実装してみました。 内容に誤り等ございましたらコメントにてご教授いただけますと幸いです。 例題 下記2つのデータフレームを作成・結合し、合計、平均値を追加する 品名 原価 売価 利益 0 りんご 100 120 20 1 みかん 50 60 10 2 かき 80 100 20 品名 原価 売価 利益 0 もも 90 120 30 py #STEP1:データフレームを作成する data1 = pd.DataFrame({'品名': ['りんご', 'みかん', 'かき'], '原価': [100, 50, 80], '売価': [120, 60, 100], '利益': [ 20, 10, 20]}) data2 = pd.DataFrame({'品名': ['もも'], '原価': [90], '売価': [120], '利益': [ 30]}) # STEP2:データフレームを結合する data1 = pd.concat([data1,data2],axis=0) data1 = data1.reset_index() # 新しくインデックスを振りなおす data1.drop(['index'],axis=1,inplace=True) # 古いインデックスがindexという名前のカラムで保存されているため消す # STEP3:合計値を表示する data1["合計"] = data1.sum(axis=1) # 合計カラムを追加し、横方向の合計を代入する data1.loc[4] = data1.sum() # インデックスを追加し、縦方向の合計を代入する data1.loc[4,"品名"]=["合計"] # 追加したインデックスの品名カラムを合計に書き換える # STEP4:平均値を表示する data_body = data1.head(4) # 上から4つのデータを抽出する data1.loc[5] = data_body.mean() # インデックスを追加し、抽出したデータの平均を代入する # data1.loc[5] = data1.head(4).mean() # 上記2行をまとめて書くならこう data1.loc[5,"品名"]=["平均"] # 追加したインデックスの品名カラムを平均に書き換える ######おまけ###### # 作成したデータフレームは小数点が入っているため、整数値に直す data1.loc[:,"原価":"合計"].astype("int") # CSVとして保存 data1.to_csv("data1.csv",index=False) # インデックスの番号は保存しない # CSVを呼び出す data_csv = pd.read_csv("data1.csv") 完成品 まとめ 今回の例題で出力した合計値、データとしては全く役に立ちませんね(笑) これ出したからって何に使うんや。。ってちょっと思ってしまいましたが、「コードを使ってみる」というテーマなのでご容赦ください! まだまだ学ぶことはたくさんありますが、少しずつ理解を深めていきたいと思います!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Chainer チュートリアル学習記録 Python篇

チュートリアル学習の背景 現在、機械学習の勉強をしているが、本に書かれているコードについて解説を読めばなんとなくやっていることは分かるが、自分でそのコードを1から書けと言われても書けない状況を打開したいと思っていた pandasのSeriesとDataFrameの違いや要素へのアクセスなど、その都度調べる勉強方法がいいのか、一度、pandasやnumpyなどのチュートリアルをやってみたほうがいいのか考え中 「その都度」のメリット・デメリット メリット その都度調べるから必要な量だけを実践的に知ることができる デメリット 体系的に身につかない 「チュートリアル」のメリット・デメリット メリット 体系的に身につく 良い資料(本当に必要なだけの内容を計算している)を使えば、体系的な学習のデメリットである時間がかかることを後々回収できる可能性がある デメリット 悪い資料(使用頻度の低いものまで掲載している)を使うと、体系的学習に時間と労力がかかる 色々と考えたが、時間があること、新卒一年目なので基礎からやっていたほうが時間がかかっても後々回収できること、チュートリアルがChainerの開発を過去に手掛けていた株式会社Preferred Networksが公開した資料であることから、機械学習の勉強を一旦ストップして、チュートリアル学習をすることに決めた。 参考文献: ディープラーニング入門Chainer チュートリアル 以下、自分の理解が微妙な部分だけ抜粋して行った記録である。 エスケープシーケンス print('hello\nworld') hello world print('hello\tworld') hello world 文字列メソッド name = 'akihiro' type(name) str name = name.upper() name 'AKIHIRO' name = name.lower() name 'akihiro' print('{}、チュートリアルへようこそ'.format(name)) akihiro、チュートリアルへようこそ 浮動小数点メソッド 0.5.as_integer_ratio() (1, 2) 0.25.as_integer_ratio() (1, 4) 複合データ型 リスト・・・編集可能 nums = [1,2,3,4,5] len(nums) 5 type(nums) list nums[1] 2 nums[0] 1 nums[:5] [1, 2, 3, 4, 5] nums[0:4] [1, 2, 3, 4] nums[0:] [1, 2, 3, 4, 5] nums[-1] 5 nums[-2] 4 nums[-4] 2 nums[:] [1, 2, 3, 4, 5] # 文字列と数値列の両方を同時に格納できる arr = [[2020, 'Tokyo'], [2024, 'Pari']] arr [[2020, 'Tokyo'], [2024, 'Pari']] arr.append([2016, 'Rio']) arr [[2020, 'Tokyo'], [2024, 'Pari'], [2016, 'Rio']] #空のリストを用意して要素を追加 list = [] list.append('Chainer') list.append('チュートリアル') list ['Chainer', 'チュートリアル'] タプル・・・中の要素を変更できない arr = (1,2,3,4,5) arr (1, 2, 3, 4, 5) type(arr) tuple arr[3] 4 arr[:] (1, 2, 3, 4, 5) 先述の通り、タプルは各要素の値を変更することができません。 この性質は、定数項などプログラムの途中で書き換わってしまうことが望ましくないものをまとめて扱うのに便利です。 # 値を変えようとするとエラーとなる arr[0] = 10 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-48-668a784d059e> in <module> 1 # 値を変えようとするとエラーとなる ----> 2 arr[0] = 10 TypeError: 'tuple' object does not support item assignment tuple のように中身が変更できない性質のことをイミュータブル (immutable)であると言います。反対に、list のように中身が変更できる性質のことをミュータブル (mutable)であると言います 辞書 リストやタプルでは、各要素にアクセスする際に整数のインデックスを用いていましたが、辞書ではキーでインデックス化されているため、整数や文字列など、色々なものを使って要素を指定することができます。 scores = {'Math': 40, 'English': 89, 'Japanese': 76} scores {'Math': 40, 'English': 89, 'Japanese': 76} type(scores) dict scores['Math'] 40 scores['English'] 89 他の人が定義した辞書に、どのようなキーが存在するのかを調べたいときがあります。 辞書には、そのような場合に使える便利なメソッドがいくつか存在します。 - keys(): キーのリストを取得。dict_keys というリストと性質が似た型が返る - values(): 値のリストを取得。dict_values というリストと性質が似た型が返る - items(): 各要素の (key, value) のタプルが並んだリストを取得。dict_items というリストと性質が似た型が返る scores.keys() dict_keys(['Math', 'English', 'Japanese']) scores.values() dict_values([40, 89, 76]) scores.items() dict_items([('Math', 40), ('English', 89), ('Japanese', 76)]) dict_keys, dict_values, dict_items と新しい型が登場しましたが、これは辞書型特有の型であり厳密には標準のリストとは異なりますが、リストと性質の似た型であるという程度の認識で問題ありません。 辞書に要素を追加する場合は、新しいキーを指定して値を代入します。 scores['Science'] = 99 scores {'Math': 40, 'English': 89, 'Japanese': 76, 'Science': 99} scores['Math'] = 55 scores {'Math': 55, 'English': 89, 'Japanese': 76, 'Science': 99} 制御構文 繰り返し(for文) names = ['akihiro', 'tomohiro', 'kiyomi', 'atsushi', 'coco'] for i in range(5): print(names[i]) akihiro tomohiro kiyomi atsushi coco for i in range(5): print('{}さん'.format(names[i])) akihiroさん tomohiroさん kiyomiさん atsushiさん cocoさん for i in range(len(names)): print('{}さん'.format(names[i])) akihiroさん tomohiroさん kiyomiさん atsushiさん cocoさん これでリストの要素数に依存しないプログラムにすることができました。 また、リスト自体をイテラブルオブジェクトとして指定することにより、リスト要素数の取得も [] でのインデックス番号の指定もせずに、より可読性の高いプログラムを書くことができます。 for name in names: print('{}さん'.format(name)) akihiroさん tomohiroさん kiyomiさん atsushiさん cocoさん リストをイテラブルオブジェクトとして指定した場合、要素番号を取得できませんが、状況によっては要素番号を使用したいことがあります。 そのような場合は、enumerate() という組み込み関数を使います。 これにイテラブルオブジェクトを渡すと、(要素番号, 要素) というタプルを 1 つずつ返すイテラブルオブジェクトになります。 for i, name in enumerate(names): message = '{}番目:{}さん'.format(i, name) print(message) 0番目:akihiroさん 1番目:tomohiroさん 2番目:kiyomiさん 3番目:atsushiさん 4番目:cocoさん enumerate() と同様、for 文と合わせてよく使う組み込み関数に zip() があります。 zip() は、複数のイテラブルオブジェクトを受け取り、その要素のペアを順番に返すイテラブルオブジェクトを作ります。 このイテラブルオブジェクトは、渡されたイテラブルオブジェクトそれぞれの先頭の要素から順番に、タプルに束ねて返します。 このイテラブルオブジェクトの長さは、渡されたイテラブルオブジェクトのうち最も短い長さと一致します。 names = ['Python', 'Chainer'] versions = ['3.7', '5.3.0'] suffixes = ['!!', '!!', '?'] for name, version, suffix in zip(names, versions, suffixes): print('{} {} {}'.format(name, version, suffix)) Python 3.7 !! Chainer 5.3.0 !! suffixes の要素数は 3 ですが、より短いイテラブルオブジェクトと共に zip に渡されたため、先頭から 2 つ目までしか値が取り出されていません。 関数 関数の引数のデフォルト値 def hello(message='Chainerチュートリアルへようこそ!'): print(message) hello() Chainerチュートリアルへようこそ! hello('Welcome to Chainer tutorial!') # 上書きが可能 Welcome to Chainer tutorial! 変数のスコープ a = 1 def change(): a = 2 print('inside a = ', a) change() print('outside a = ', a) inside a = 2 outside a = 1 a = 1 def change1(): print('from inside:', a) # 関数内で定義していないため、関数外の変数を参照することは出来る change1() print('from outside:', a) from inside: 1 from outside: 1 関数の外で定義された変数はグローバル変数と呼ばれます。 グローバル変数は、特に特別な記述を要せず参照することはできますが、関数の中で代入を行う場合は、global 文を使って、代入先をグローバル変数とする宣言を行う必要があります。 a = 1 def change(): global a a = 2 change() a 2 クラス class HOUSE: def __init__(self, name): self.name_plate = name init() はそういったメソッドの一つで、インスタンス化する際に自動的に呼ばれるメソッドです。 House クラスの init() は、name という引数をとり、これを self.name_plate という変数に代入しています。 この self というのは、クラスがインスタンス化されたあと、作成されたインスタンス自身を参照するのに用いられます。 これを使って、self.name_plate = name とすることで、作成された個別のインスタンスに属する変数 self.name_plate へ、引数に渡された name が持つ値を代入することができます。 self が指すものは、各インスタンスから見た「自分自身」なので、各インスタンスごとに異なります。 これによって、self.name_plate は各インスタンスに紐付いた別々の値を持つものとなります。 my_house = HOUSE('Chainer') House というクラスの init() メソッドに、'Chainer' という文字列を渡しています。 my_house が、House クラスから作成されたインスタンスです。 ここで、クラス定義では init() メソッドは self と name という 2 つの引数をとっていましたが、呼び出しの際には 'Chainer' という一つの引数しか与えていませんでした。 この 'Chainer' という文字列は、1 つ目の引数であるにも関わらず、init() メソッドの定義では 2 つ目の引数であった name に渡されます。 前述のように、メソッドは、インスタンスから呼び出されるとき自動的に第一引数にそのインスタンスへの参照を渡すためです。 この自動的に渡される自身への参照は、呼び出しの際には明示的に指定しません。 また、かならず 1 つ目の引数に自動的に渡されるため、呼び出し時に明示的に与えられた引数は 2 つ目以降の引数に渡されたものとして取り扱われます。 class HOUSE: def __init__(self, name): self.name_plate = name def hello(self): print('{}さんの家です'.format(self.name_plate)) sato = HOUSE('Sato') suzuki = HOUSE('Suzuki') sato.hello() suzuki.hello() Satoさんの家です Suzukiさんの家です このように、同じ機能を持つが、インスタンスによって保持するデータが異なったり、一部の動作が異なったりするようなケースを扱うのにクラスを利用します。 Python の int 型、float 型、str 型…などは、実際には int クラス、float クラス、str クラスであり、それらの中では個別の変数(インスタンス)がどのような値になるかには関係なく、同じ型であれば共通して持っている機能が定義されています。 5 や 0.3 や 'Chainer' などは、それぞれ int クラスのインスタンス、float クラスのインスタンス、str クラスのインスタンスです 継承 class Link: def __init__(self): self.a = 1 self.b = 2 l = Link() l.a 1 l.b 2 このクラスを継承する、Chain というクラスを定義してみます。 継承を行う場合は、クラス定義の際にクラス名に続けて () を書き、その中にベースにしたいクラスの名前を書きます。 () の中に書かれたクラスのことを、定義されるクラスの親クラスといいます。 それに対し、() の中に書かれたクラスからみると、定義されるクラスは子クラスと呼ばれます。 親から子へ機能が受け継がれるためです。 class Chain(Link): def sum(self): return self.a + self.b c = Chain() c.a 1 c.b 2 c.sum() 3 class Chain(Link): def __init__(self): self.c = 5 def sum(self): return self.a + self.b + self.c c = Chain() c.sum() --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-114-92631ebf55a8> in <module> ----> 1 c.sum() <ipython-input-112-fc5a883e4286> in sum(self) 5 6 def sum(self): ----> 7 return self.a + self.b + self.c 8 9 AttributeError: 'Chain' object has no attribute 'a' 'Chain' というオブジェクトは、'a' という名前の属性を持っていない、と言われています。 a という属性は、Chain の親クラスである Link の init() メソッドで定義されています。 そのため、Chain クラスをインスタンス化する際に、親クラスである Link の init() メソッドが呼ばれているのであれば、このエラーは起こらないはずです。 なぜエラーとなってしまったのでしょうか。 それは、Chain クラスにも init() メソッドを定義したため、親クラスである Link の init() メソッドが上書きされてしまい、実行され>なかったためです。 しかし、親クラスの init() メソッドを明示的に呼ぶことで、これは解決できます. それには、super() という組み込み関数を用います。 これを用いると、子クラスから親クラスを参照することができます。 class Chain(Link): def __init__(self): # 親クラスの `__init__()` メソッドを呼び出す super().__init__() self.c = 5 def sum(self): return self.a + self.b + self.c c = Chain() print('a, b, c = [{}, {}, {}]'.format(c.a, c.b, c.c)) print(c.sum()) a, b, c = [1, 2, 5] 8 # あるクラスを継承して作られたクラスを、さらに継承して別のクラスを定義することもできます。 class MyNetwork(Chain): def mul(self): return self.a * self.b * self.c net = MyNetwork() print('a, b, c = [{}, {}, {}]'.format(net.a, net.b, net.c)) print(net.mul()) a, b, c = [1, 2, 5] 10
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

データ分析メモ

はじめに 以下のUdemy講座の学習メモです。 やさしい実用統計 Pythonによるデータ分析入門 統計の分野 大きく4つあります。企業で一般的に利用される統計は記述統計です。 記述統計(ほかの統計分野の基礎でもある) データの情報収集 推測統計(統計の中心的な理論) 部分から全体を推定 ベイズ統計 データに基づく確率的推移 多変量解析 多変量データのモデリング 記述統計 データの情報収集。データを集約して情報を抽出する方法の総称。 主な方法は次の通り。 データの分布を確認する 代表値を調べる 散布度を調べる 変量を標準化する データ分析の目的 データ分析は必ずおおもとの課題につながるものでなければならない。 データ分析の結果から施策が立案・実行されることが大切。施策が実行されて初めてデータ分析が成功したか否かがわかる。 データ分析の種類 2種類に分類できます。 求解:求める結果が明確に定義されている 探索:データの中から何かを発見する調査 データ分析プロジェクトの作業と作業量 計画(5%) データ収集(5%) データクレンジング(60%) 本格的なデータ分析(20%) 結果解釈~活用への提言(10%) 必要なスキルと知識 本来業務の知識 統計の知識 プログラミングスキル データ分析ツールの知識 プロジェクト管理 データプロファイリング いつどこでだれが何のためにどのようにして集めたのかを調べてデータの前提を明確にすることが大切 データの発生目的 今回のデータ分析のために集められたデータ 別の目的のために集められたデータの流用 母集団と標本 母集団:分析対象全体 標本(サンプル):分析対象の一部 紙データと電子データのギャップ データ発生システムの特徴 変数名の規則 英字で始まる半角英数字を使用する 特殊文字や全角文字は使用しない 英語で意味の通じる名称にする 複数の単語をつなげる場合はcamelCaseにする データ加工の原則 データの修正・加工のプロセスにおいて、加工ミスの防止と再現性の保証のためルールを守ります。 オリジナルデータの保管 プログラムによる加工(再現性のない手作業は行わない) 履歴管理 Pythonの重要なライブラリー NumPy(import numpy as np) 用途:高速の配列計算。 通常の配列ではできない計算を行うためのメソッドがたくさん用意されています。計算精度と計算速度に配慮されているため科学技術計算での利用に適しています。 pandas(import pandas as pd) 用途:データフレーム 表形式のデータ構造で、データ分析に必要な様々な機能を備えています。 matplotlib(import matplotlib.pyplot as plt) 用途:グラフ描画 用語 代表値 データの特徴を一つの値で表したモノです。 主な代表値として、平均値、中央値、最頻値、その他の代表値として最大値、最小値、トリム平均、分位数があります。 散布度 データのばらつき度合いをあらわす指標で、代表値を補足する情報。 変量の標準化 異なる変量を比較するためにデータの標準化を行います。 変量の標準化には、標準化変量、偏差値、正規化があります。 変量 異なる値をとり得る量 平均値 算術平均、幾何平均、調和平均があります。 階級化 数値データの範囲をいくつかの区間に区切ることを階級。各階級の中心の値を階級値。 データの値を所属する区間の階級値で表すことを階級化と言います。 度数分布表 階級化したデータを各階級で集計した結果をまとめた表を度数分布表と言います。 項目としては、階級値、度数、相対度数、累積度数、相対累積度数があります。 散布度 データのばらつき度合いを示す統計量 ヒストグラム 度数分布表の内容を横軸に数値データの範囲、縦軸に度数あるいは相対度数の値をとったグラフ。 中央値 数値データを昇順にソートして並び順の真ん中にくる値 分位数 数値データを昇順にソートして、同じ個数のK個のグループに分けた時の区切り地をK分位数と言います。主な分位数として、中央値(二分位数)、四分位数、パーセンタイル(百分位数)があります。 最頻値 度数分布表において、頻度が最大となる階級値のこと。 トリム平均 データの最大値側と最初内側から数個を除外したデータの平均をとったモノ 平均偏差 各変量の値と平均値の差の絶対値の平均 中央値絶対偏差 各データと中央値の差の絶対値をとり、その値を照準に並べた時の中央値 外れ値 その値が他の値に比較して極端に大きくは離れている値。統計手法により何を外れ値とするかは異なる。 有限事象 何かの事象が発生する可能性があるとして、可能な事象のパターンが有限個である場合
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

OSMnxのインストールで苦労した話

OSMnx インストール方法 私がいつも使っていた環境でインストールしようとしたものの、 見事にインストール失敗。3日以上かかってしまいました...。 頑張ったので書いておきます。 決め手はこちらのサイトなりました。感謝 環境 windows10   64bit home Python    3.9.5  64bit fiona     1.8.20 GDAL     3.2.2 rtree     0.9.4  ←あえてこのバージョンにした。 geopandas  0.9.0 osmnx    1.1.1 networkx   2.6.2 私の環境では以下が足りなかったです... shapely   1.7.1 six     1.16.0 pyproj    3.2.0 descartes  1.1.0 OSmnxを使うときに必須になるパッケージが多数あります。 geopandas rtree geopandasインストールに必要なパッケージ numpy pandas (version 0.15.2 or later) shapely fiona six pyproj descartes 全てconda-forgeにしました。 最終環境 # packages in environment at C:\Users\mashiko\anaconda3\envs\notebook: # # Name Version Build Channel affine 2.3.0 py_0 conda-forge argon2-cffi 20.1.0 py39h2bbff1b_1 async_generator 1.10 pyhd3eb1b0_0 attrs 21.2.0 pyhd3eb1b0_0 backcall 0.2.0 pyhd3eb1b0_0 bleach 3.3.0 pyhd3eb1b0_0 boost-cpp 1.74.0 h5b4e17d_4 conda-forge branca 0.4.2 pyhd8ed1ab_0 conda-forge brotlipy 0.7.0 py39hb82d6ee_1001 conda-forge bzip2 1.0.8 h8ffe710_4 conda-forge ca-certificates 2021.5.30 h5b45459_0 conda-forge cairo 1.16.0 hb19e0ff_1008 conda-forge certifi 2021.5.30 py39hcbf5309_0 conda-forge cffi 1.14.5 py39hcd4344a_0 cfitsio 3.470 h0af3d06_7 conda-forge chardet 4.0.0 py39hcbf5309_1 conda-forge charset-normalizer 2.0.4 pypi_0 pypi click 7.1.2 pyh9f0ad1d_0 conda-forge click-plugins 1.1.1 py_0 conda-forge cligj 0.7.2 pyhd8ed1ab_0 conda-forge colorama 0.4.4 pyhd3eb1b0_0 cryptography 3.4.7 py39hd8d06c1_0 conda-forge curl 7.78.0 h789b8ee_0 conda-forge cycler 0.10.0 py_2 conda-forge decorator 4.4.2 py_0 conda-forge defusedxml 0.7.1 pyhd3eb1b0_0 descartes 1.1.0 py_4 conda-forge entrypoints 0.3 py39haa95532_0 expat 2.4.1 h39d44d4_0 conda-forge fiona 1.8.20 py39h9f1b043_0 conda-forge folium 0.12.1 pypi_0 pypi fontconfig 2.13.1 h1989441_1005 conda-forge freetype 2.10.4 h546665d_1 conda-forge freexl 1.0.6 ha8e266a_0 conda-forge gdal 3.2.2 py39h6795fcd_7 conda-forge geopandas 0.9.0 pyhd8ed1ab_1 conda-forge geopandas-base 0.9.0 pyhd8ed1ab_1 conda-forge geos 3.9.1 h39d44d4_2 conda-forge geotiff 1.6.0 ha8a8a2d_6 conda-forge gettext 0.19.8.1 h1a89ca6_1005 conda-forge hdf4 4.2.15 h0e5069d_3 conda-forge hdf5 1.10.6 nompi_h5268f04_1114 conda-forge icu 68.1 h0e60522_0 conda-forge idna 3.2 pypi_0 pypi importlib-metadata 3.10.0 py39haa95532_0 importlib_metadata 3.10.0 hd3eb1b0_0 intel-openmp 2021.3.0 h57928b3_3372 conda-forge ipykernel 5.3.4 py39h7b7c402_0 ipython 7.22.0 py39hd4e2768_0 ipython_genutils 0.2.0 pyhd3eb1b0_1 jbig 2.1 h8d14728_2003 conda-forge jedi 0.17.2 py39haa95532_1 jinja2 3.0.0 pyhd3eb1b0_0 joblib 1.0.1 pyhd8ed1ab_0 conda-forge jpeg 9d h8ffe710_0 conda-forge jsonschema 3.2.0 py_2 jupyter_client 6.1.12 pyhd3eb1b0_0 jupyter_core 4.7.1 py39haa95532_0 jupyterlab_pygments 0.1.2 py_0 kealib 1.4.14 h96bfa42_2 conda-forge kiwisolver 1.3.2 py39h2e07f2f_0 conda-forge krb5 1.19.2 hbae68bd_0 conda-forge lcms2 2.12 h2a16943_0 conda-forge lerc 2.2.1 h0e60522_0 conda-forge libblas 3.9.0 11_win64_mkl conda-forge libcblas 3.9.0 11_win64_mkl conda-forge libcurl 7.78.0 h789b8ee_0 conda-forge libdeflate 1.7 h8ffe710_5 conda-forge libffi 3.3 h0e60522_2 conda-forge libgdal 3.2.2 ha6cada3_7 conda-forge libglib 2.68.4 h1e62bf3_0 conda-forge libiconv 1.16 he774522_0 conda-forge libkml 1.3.0 h9859afa_1014 conda-forge liblapack 3.9.0 11_win64_mkl conda-forge libnetcdf 4.8.0 nompi_hf689e7d_103 conda-forge libpng 1.6.37 h1d00b33_2 conda-forge libpq 13.3 hfcc5ef8_0 conda-forge librttopo 1.1.0 hb340de5_6 conda-forge libsodium 1.0.18 h62dcd97_0 libspatialindex 1.9.3 h39d44d4_4 conda-forge libspatialite 5.0.1 h762a7f4_5 conda-forge libssh2 1.10.0 h680486a_0 conda-forge libtiff 4.3.0 h0c97f57_1 conda-forge libwebp-base 1.2.1 h8ffe710_0 conda-forge libxml2 2.9.12 hf5bbc77_0 conda-forge libzip 1.8.0 hfed4ece_0 conda-forge lz4-c 1.9.3 h8ffe710_1 conda-forge m2w64-gcc-libgfortran 5.3.0 6 m2w64-gcc-libs 5.3.0 7 m2w64-gcc-libs-core 5.3.0 7 m2w64-gmp 6.1.0 2 m2w64-libwinpthread-git 5.0.0.4634.697f757 2 mapclassify 2.4.3 pyhd8ed1ab_0 conda-forge markupsafe 2.0.1 py39h2bbff1b_0 matplotlib-base 3.4.3 py39h581301d_0 conda-forge mistune 0.8.4 py39h2bbff1b_1000 mkl 2021.3.0 hb70f87d_564 conda-forge msys2-conda-epoch 20160418 1 munch 2.5.0 py_0 conda-forge nbclient 0.5.3 pyhd3eb1b0_0 nbconvert 6.0.7 py39haa95532_0 nbformat 5.1.3 pyhd3eb1b0_0 nest-asyncio 1.5.1 pyhd3eb1b0_0 networkx 2.6.2 pyhd8ed1ab_0 conda-forge notebook 6.4.0 py39haa95532_0 numpy 1.21.2 py39h6635163_0 conda-forge olefile 0.46 pyh9f0ad1d_1 conda-forge openjpeg 2.4.0 hb211442_1 conda-forge openssl 1.1.1l h8ffe710_0 conda-forge osmnx 1.1.1 pyhd8ed1ab_0 conda-forge packaging 20.9 pyhd3eb1b0_0 pandas 1.3.2 py39h2e25243_0 conda-forge pandoc 2.12 haa95532_0 pandocfilters 1.4.3 py39haa95532_1 parso 0.7.0 py_0 pcre 8.45 h0e60522_0 conda-forge pickleshare 0.7.5 pyhd3eb1b0_1003 pillow 8.3.2 py39h916092e_0 conda-forge pip 21.1.1 py39haa95532_0 pixman 0.40.0 h8ffe710_0 conda-forge poppler 21.03.0 h9ff6ed8_0 conda-forge poppler-data 0.4.10 0 conda-forge postgresql 13.3 h1c22c4f_0 conda-forge proj 8.0.1 h1cfcee9_0 conda-forge prometheus_client 0.10.1 pyhd3eb1b0_0 prompt-toolkit 3.0.17 pyh06a4308_0 pycparser 2.20 py_2 pygments 2.9.0 pyhd3eb1b0_0 pyopenssl 20.0.1 pyhd8ed1ab_0 conda-forge pyparsing 2.4.7 pyhd3eb1b0_0 pyproj 3.2.0 py39ha996c60_0 conda-forge pyrsistent 0.17.3 py39h2bbff1b_0 pysocks 1.7.1 py39hcbf5309_3 conda-forge python 3.9.5 h6244533_3 python-dateutil 2.8.1 pyhd3eb1b0_0 python_abi 3.9 2_cp39 conda-forge pytz 2021.1 pyhd8ed1ab_0 conda-forge pywin32 228 py39he774522_0 pywinpty 0.5.7 py39haa95532_0 pyzmq 20.0.0 py39hd77b12b_1 rasterio 1.2.6 py39hb4f844e_1 conda-forge requests 2.26.0 pyhd8ed1ab_0 conda-forge rtree 0.9.4 py39h09fdee3_2 conda-forge scikit-learn 0.24.2 py39he931e04_1 conda-forge scipy 1.7.1 py39hc0c34ad_0 conda-forge send2trash 1.5.0 pyhd3eb1b0_1 setuptools 52.0.0 py39haa95532_0 shapely 1.7.1 py39haadaec5_5 conda-forge six 1.16.0 pyh6c4a22f_0 conda-forge snuggs 1.4.7 py_0 conda-forge sqlite 3.36.0 h8ffe710_0 conda-forge tbb 2021.3.0 h2d74725_0 conda-forge terminado 0.9.4 py39haa95532_0 testpath 0.4.4 pyhd3eb1b0_0 threadpoolctl 2.2.0 pyh8a188c0_0 conda-forge tiledb 2.3.4 h78dabda_0 conda-forge tk 8.6.11 h8ffe710_1 conda-forge tornado 6.1 py39h2bbff1b_0 traitlets 5.0.5 pyhd3eb1b0_0 tzdata 2020f h52ac0ba_0 urllib3 1.26.6 pyhd8ed1ab_0 conda-forge vc 14.2 h21ff451_1 vs2015_runtime 14.27.29016 h5e58377_2 wcwidth 0.2.5 py_0 webencodings 0.5.1 py39haa95532_1 wheel 0.36.2 pyhd3eb1b0_0 win_inet_pton 1.1.0 py39hcbf5309_2 conda-forge wincertstore 0.2 py39h2bbff1b_0 winpty 0.4.3 4 xerces-c 3.2.3 h0e60522_2 conda-forge xz 5.2.5 h62dcd97_1 conda-forge zeromq 4.3.3 ha925a31_3 zipp 3.4.1 pyhd3eb1b0_0 zlib 1.2.11 h62dcd97_1010 conda-forge zstd 1.5.0 h6255e5f_0 conda-forge Note: you may need to restart the kernel to use updated packages. やったこと pip echo y | pip uninstall <アンインストールする物> Conda conda install -c conda-forge <インストールする物> 学んだこと pip と conda は混ぜないこと。 入れる順番によってはコンフリクトを起こしてしまう事。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Django rest_framework にてカスタムのレスポンスステータス・ボディを返却する方法について

概要 Django rest_framework を利用して API を設計しています。 アプリケーションでは、別サーバーへ HTTP アクセスしています。 HTTP アクセスが失敗して、なにもハンドリングをしないと、自前の Django アプリケーションで 500 エラーが発生してしまいます。 500 エラーは「うっかり」ででるような類のサーバーエラーのニュアンスがあるように感じられたので、起きうることは予想できるけれど、どうしようもない例外ということで 502 エラー を返そうとしました。 Spring MVC のようなことができることを想定していたのですが、既定の機能では、レスポンスステータスを、502 で返す方法がなさそうなので、カスタムのレスポンスを返却する方法を調査しました。 環境 Python: 3.9 Django: 3.1.4 Django Rest Framework: 3.12.2 実現方法 公式ページのやり方を模倣するだけで実現できました。 rest_framework.exceptions.APIException を継承したクラスを作成します。 status_code : ステータスコード detail: レスポンスボディのメッセージ となりました。 from dataclasses import dataclass from rest_framework.exceptions import APIException @dataclass(frozen=True) class ServerNotWorkedResponse(APIException): source_exception: Exception # 元となった例外 message: str status_code = 502 detail = "外部サーバーへのアクセスに失敗しました。" このクラスを try catch でハンドルします。 もしも、リクエストする関数をモジュール化している場合、戻り値を Union に設定して、呼び出し元 (アプリケーションレイヤー) で最後の振る舞いを決めることができます。 ライブラリの中でいきなり例外を投げたると、関数の本当の目的 (外部サーバーにアクセスしてレスポンスを利用元に返す) 以外に、「外部サーバーへのアクセスに失敗すると例外が発生する」という機能が入り込み、結果としてモなにか予想外のことがおきる、副作用があるライブラリになります。一番外側の利用元で最後の振る舞いを決める設計にすると、副作用を減らしたライブラリ設計を実現するための手段として活用できます。 import json from dataclasses import dataclass import ServerNotWorkedResponse from typing import Union, cast from urllib import request from urllib.error import HTTPError, URLError @dataclass(frozen=True) class ExampleDomainResponse: id: int, name: str # 呼び出し先 def request_towards_example(id: int) -> Union[ServerNotWorkedResponse, ExampleDomainResponse]: req = request.Request(f'https://example.domain.io/resources/{id}') try: with request.urlopen(req) as res: resource = json.loads(res.read()) except HTTPError as e return ServerNotWorkedResponse(source_exception=e, message='サーバーがエラーを返してきました。') except URLError as e: return ServerNotWorkedResponse(source_exception=e, message='このサーバーは名前解決ができませんでした。URL を解決できるよう設定してください。') else: return ExampleDomainResponse( id=cast(int, resource['id']) name=resource['name'] ) # 最も外側の呼び出し元 response_from_example: Union[ServerNotWorkedResponse, ExampleDomainResponse] = request_towards_example(1) if isinstance(response_from_example, ServerNotWorkedResponse): server_not_worked = cast(ServerNotWorkedResponse, response_from_example) logger.error(server_not_worked.source_error) logger.error(server_not_worked.message) raise server_not_worked
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者向け Pythonプログラミング基礎 #1

目的 プログラム言語の一つであるPythonの使い方の基礎を学ぶ. また,特に指定がない場合下記のようにプログラムの実行結果を示す. >>>この部分は実行結果を表示 Python3 インタプリタ型のプログラミング言語のひとつ. ※Python3とPython2は互換性がない. インデントが構文規則として使用されており,書きやすく読みやすいという特徴がある. 使われる分野が広く機械学習でも使用される. プログラミング言語 : コンピュータ言語の内コンピュータプログラムを記述するための言語. インタプリタ型 : プログラムを実行する手段の一つ.ソースコードを1行ずつ読みこみ実行命令として,動作する. Pythonのオブジェクト Pythonのオブジェクトとは,Pythonで操作するデータとのことである. 複雑な構造にさせることもでき,行列などを簡単に表現できる. 詳しくは,難しいのでおいおい説明する. コメントの記述 各行の#以降はコメントとして認識され,プログラムとしては実行されない. また,"または'を3つずつで前後を囲うことで複数行をコメントアウトできる. 実行内容のコメントを記載する時に使用する. #コメント行 """ コメント行 """ プログラム内で日本語を使う場合 Pythonのプログラムで日本語を使う場合,最初に文字コードを指定する必要がある. 1行目は,Pythonのパスを記載する.こうすることで,明示的に実行コマンドを指定しなくてもPython3で実行してくれる. 2行目は,文字コードを記載する.自分の環境の文字コードを指定する. #!/usr/bin/python3 #! -*- coding:utf-8 -*- print("こんにちは") Pythonのデータ型 Pythonの基本のデータ型を説明する. 変数 変数は値につける名前である. プログラムが終了するまで,その変数は保持され,変数を指定することで,その値を代入できる. a = 2 a + 1 #3を返す a / 2 #1を返す 数値 Pythonにおいて,数をそのまま記載すると数値型として扱われる. ()を使うことで,一般的な数式同様に計算の優先度を変更できる. a = 2 + 1 # 足し算 a = 3 - 1 # 引き算 a = 2 * 3 # 掛け算 a = 5 / 2 # 割り算 a = 7 % 2 # あまり a = (2 + 3)*5 文字列 "または'で前後を囲うことで文字列型として扱われる. 文字列は+で結合させることが可能. 数値も"または'で囲うことで,文字列として認識されるため注意が必要. a = "こんにちは" b = "おはよう" c = "5" a + b >>>'こんにちはおはよう' Boolean BooleanはTrueまたはFalseの2つの値を指す. while文やif文を使う際に条件として使用することが多い. また,条件文として,True,Falseを返却するようにすることができる. a = True b = False c = 1 c > 0.5 # Trueを返す c == 1 # Trueを返す c > 2 # Falseを返す List Listは[]を使って定義することができる. l = [2, 4, 6, 8, 10] l[0] #ゼロベースのインデックスを使って特定の数値を呼び出せる >>>2 l[1:5:2] # [start:stop:step]を指定することでstartからstopまでstep間隔で呼び出せる >>>[4, 8] m = [1, 3, 5, 7, 9] l + m >>>[2, 4, 6, 8, 10, 1, 3, 5, 7, 9] n = l + m n.sort() n >>>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] n.append(100) n >>>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100] n.pop() # 末尾の要素を取り出す >>>100 n >>>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1,1,1,2,2,3].count(1) # countで指定した値がいくつあるかを返す >>>3 リストの内包表記 Pythonでは,リスト内表記が使用できる. for文やifを使用して新たなリストに変換できる. l = [2,4,6,8,10] [x for x in l if x > 6] # 条件に合う値のみ抽出 >>>[8, 10] [x*5 for x in l] >>>[10, 20, 30, 40, 50] # 全部の値に5を掛けてリストを作成 l = ['hello','world'] [x.upper() for x in l] # 文字列をすべて大文字に変換したリストを作成 >>>['HELLO', 'WORLD'] Tuple Tupleは複数のオブジェクトを一つにまとめたものである. ()を使用して定義する. a = ('baba', 35) b = a # そのまま別の変数に代入できる >>>('baba', 35) c, d = a # それぞれの値を分割して変数に代入することもできる c >>>'baba' d >>>35 Set Setは,順序付けされていない一意の要素で構成される. すなわち集合を構成するためのものである. l = ['a', 'a', 'b', 'c', 'c', 'a'] set(l) # 重複要素を除去 >>>{'a', 'b', 'c'} set('Hello') # 文字列を集合化 >>>{'H', 'e', 'l', 'o'} a = set('Hello') b = set('World') a - b #aに含まれてbに含まれない要素 >>>{'H', 'e'} a | b # aまたはbに含まれる要素 >>>{'H', 'W', 'd', 'e', 'l', 'o', 'r'} a & b # aかつbに含まれる要素 >>>{'l', 'o'} a ^ b # aまたbに含まれる要素で,かつaとbのどちらかにのみ含まれる要素 >>>{'H', 'W', 'd', 'e', 'r'} a = { 1, 2, 4 } b = { 2, 3, 5 } c = { 2, 3, 4, 5 } b <= c # bがcの部分集合であるか >>>True a <= c # aがcの部分集合であるか >>>False Dictionary Dictionaryは,キーと値のペアを保持するオブジェクトである. {}を使って,キーと値のペアを定義する. d = {'name':'baba', 'age':35} d['name'] >>>'baba' d['car'] = 'Juke' # 後から要素を追加することも可能 d >>>{'name': 'baba', 'age': 35, 'car': 'Juke'} d.items() # キーと値を配列として変換できる >>>dict_items([('name', 'baba'), ('age', 35), ('car', 'Juke')]) 'name' in d # キーが存在するか確認 >>>True 'address' in d >>>False Pythonの制御文 制御文はプログラミングの基本となるものである. いくつかの制御文を説明する. 制御文を使用する際にはインデントを使って記述する. if文 if文では条件に合致するかそれ以外かで処理を変更できる. 複数の条件がある場合はelifを使用して,分岐を増やすことができる. m = 3 if m > 5: print('m greater than 5.') elif m > 2: print('m greater than 2.') else: print('m less than 2') 条件の関係演算子は以下のようなものがある. 演算子 意味 < より小さい <= 同じか小さい > より大きい >= 同じか大きい == 等しい != 異なる 条件の論理演算子は以下のようなものがある. 演算子 意味 and かつ or または not ではない for文 for文を使い同じ処理を何度も行うことが可能. a = ['a', 'b', 'c', 'd', 'e'] for l in a: print(l, end=', ') >>>a, b, c, d, e, breakとcontinue breakを宣言するとfor文を終了する. for l in a: if l == 'c': break print(l, end=(', ')) >>>a, b, continueを宣言するとfor文のその回の処理が終了し,次のfor文の処理に移る. for l in a: if l == 'c': continue print(l, end=(', ')) >>>a, b, d, e, while文 for文と同じように同じ処理を何度も行うことが可能. for文と違い,ループする条件をwhile文に対して指定する. breakとcontinueはfor文と同じように使用する. a = 0 while a < 10: # aが10未満の間処理を続ける a += 1 print(a, end=(', ')) >>>1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Pythonを使ってYoutubeから字幕を抽出する。

Youtubeを見ていると自動生成される字幕がでてくると思います。 今回はそれをテキスト化し抜き出してみます。 2021/09/06 さきほど動作確認したところ、エラーが出て動かなくなっていました。。 調べたところYouTube側のAPIの変更などが原因の用です。pytubeがissueを出していたのでバージョンを上げれば動作するかも。。 https://stackoverflow.com/questions/68680322/pytube-urllib-error-httperror-http-error-410-gone これでうまくいくのかな? LanguageReactorつかえば? GoogleChromeのLanguageReactorというプラグインを使うと同じようなことが搭載されています。 字幕の開始時間はとれるんですが今回は終了時刻が欲しかったので別途Pythonで実装しました。 実装 import os from pytube import YouTube #字幕出力 def outContext(url): #動画のクラス取得 yt = YouTube(url) # 動画の字幕の言語一覧 print(yt.captions.get_by_language_code) # 指定した言語の字幕取得 caption = yt.captions.get_by_language_code('a.ja') # srt形式で取得 contexts = caption.generate_srt_captions() # ファイルに出力 f = open('../字幕テキスト/' + yt.video_id + '_字幕.srt', 'w') f.write(contexts) f.close() common_url = "https://www.youtube.com/watch?v=sFPqmy1rOmA" outContext(url) 出力結果 出力を試したものはひろゆきの動画です。 https://www.youtube.com/watch?v=sFPqmy1rOmA 1 00:00:02,500 --> 00:00:05,200 いっ 2 00:00:03,820 --> 00:00:06,640 にっ 3 00:00:05,200 --> 00:00:10,210 村 4 00:00:06,640 --> 00:00:15,340 45敗えっ 5 00:00:10,210 --> 00:00:17,470 8知らせを取れちゃったんですけどあのいつもながらラグが8秒ぐらいあるんですけど 6 00:00:15,340 --> 00:00:23,400 あの今日はな具があの 7 00:00:17,470 --> 00:00:28,320 だから2秒事から柴田はちょっとあの自分のことだから勝手にびっくりしました 8 00:00:23,400 --> 00:00:32,099 えっとですねあの中いつもこう予約して時間が今日5:55いう役だったんですけど 9 00:00:28,320 --> 00:00:38,910 ちょっとあの予約時間前に初めて見たですよね
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

210911_Pythonプログラミング教室

演習問題①の解答 # 全ての果物の金額を変数に代入する apple = 100 orange = 120 # 「税抜き価格は〇〇円になります」と出力する non_taxed_price = apple * 2 + orange print('税抜き価格は' + str(non_taxed_price) + '円になります') # 「税込価格は〇〇円になります」と出力する tax_included_price = int(non_taxed_price * 1.1) print('税込み価格は' + str(tax_included_price) + '円になります') 演習問題②の解答 test_scores =[50, 65, 45, 75, 70] # 解答1) 国語の点数(50点→80点)に書き換えてください test_scores[0] = 80 # 解答2) 体育の点数(90点)を加えて出力してください test_scores.append(90) print(test_scores) # 解答3) 「最低スコアは◯点、最高スコアは◯点です。」と出力してください print("最低スコアは" + str(test_scores[2]) + "点、最高スコアは" + str(test_scores[-1]) + "点です。") 演習問題③の解答 test_scores_d ={'国語':50,'算数':65,'理科':45,'社会':75,'英語':70} # 解答1) 国語の点数(50点→80点)に書き換えてください test_scores_d['国語'] = 80 # 解答2) 体育の点数(90点)を加えて出力してください test_scores_d['体育'] = 90 print(test_scores_d) # 解答3) 「最低スコアは◯点、最高スコアは◯点です。」と出力してください print("最低スコアは" + str(test_scores_d['理科']) + "点、最高スコアは" + str(test_scores_d['体育']) + "点です。")
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Excelに書かれたセリフシートを縦書きの収録台本に変換する

1.やりたいこと こんな感じでExcelに書かれたセリフシートを、Wordの縦書き台本に変換します。 <キャラクター紹介> 自己紹介 はじめまして! オレは猫だ! よろしくな。えっ名前? まだ無いんだ、すまない 朝のあいさつ おはよう! 今日も元気そうだな 昼のあいさつ ふぁ~ ちょっと眠いな 夜のあいさつ 疲れた~! 今日はもう終わりにしよう。また明日な! 2.準備 縦書きの収録台本として、今回は配布されている「映画用脚本・シナリオ・ワード・テンプレート」を利用します。 テンプレートを開き、中の文章を全部クリアした後docx形式で保存し直します。 このテンプレートにはスタイルが複数種類登録されていて、今回は「台詞」と「柱・シーン」というスタイルを利用することにします。 importするライブラリ またExcelの読み込みにPythonのopenpyxlを、Wordの読み書きにdocxを使うので、必要に応じてpip installします。 文字列置換も利用するのでimportは下記の3つになります。 import openpyxl import docx import re Wordのリスト番号を拡張する Wordのリスト書式で丸囲い数字を使う場合、①~⑳までしか対応していません。 代替として、行頭に丸囲い数字を入れる関数toCircledを作り、行頭に追加することにします。 ベースはこちらを参考にしました。 これで1~50までは丸囲い数字のリスト風に番号を出力することができます。 #========================================================================================= # 数字を丸囲い数字に変換 #========================================================================================= def toCircled(num): if num <= 0 or num > 50: #1~50以上は丸囲い数字がないので文字列にして戻す return str(num) if num <= 20: return chr(ord('①') + num -1) if num <= 35: return chr(ord('㉑') + num -21) if num <= 50: return chr(ord('㊱') + num -36) 一部文字の変換 また不等号記号は縦書きに対応していないため、山括弧に変換します。 #========================================================================================= # 大なり小なりを山括弧に変換 #========================================================================================= def repSign(str): str = re.sub("<","〈",str) str = re.sub(">","〉",str) return str 3.処理 主な処理を書いていきます。 FILENAMEにはExcelのファイル名を、WORD_TEMPLATEにはテンプレートのdocxファイルが指定されています。 表で言う左の部分を太字、右の台詞は装飾なしで書き出します。 #ベースとなるセリフシートを読み込み wb = openpyxl.load_workbook(FILENAME) #ワークシートの分だけ処理する for ws in wb.worksheets: #テンプレートのWordファイル読み込み doc = docx.Document(WORD_TEMPLATE) num = 1 #1行目から5行目までを処理してみる for r in range(1,5): if ws.cell(r,1).value == None: continue #2列目にセリフがある場合 if ws.cell(r,2).value != None: #項目部分は太字 p = doc.add_paragraph() style = p.add_run(toCircled(num) + " " + repSign(ws.cell(r,1).value)) style.bold = True style.font.name = "MS 明朝" p.style = "台詞" #採番をインクリメント num += 1 #セリフを挿入 p = doc.add_paragraph() #行末の句読点を削除し、鍵括弧で挟んで挿入する style = p.add_run(" 「" + re.sub('。$','',repSign(ws.cell(r,2).value)) +"」") style.font.name = "MS 明朝" p.style = "台詞" p = doc.add_paragraph() p.style = "台詞" #セリフがない場合は柱として扱う else: #doc.add_page_break() p = doc.add_paragraph(repSign(ws.cell(r,1).value),style="柱・シーン") #採番をリセット num = 1 #ワークシート名で台本を保存 doc.save(ws.title + '.docx') 4.補足 インデントなどは個々人で使いやすい設定があると思うので、テンプレートのスタイルを変更することをおすすめします。 また表紙などに横書きのものを入れたい場合、Word内で1x1の表を作り、そこにテキストを挿入する方法が簡単です。 (docxではテキストボックスを取得できないようです) 表にテキストを挿入する注意点として、fontで日本語フォントを指定するだけでは反映されないことがあります。 その際は「Python-docxで日本語フォントを使いたい」が参考にしてみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Excelに書かれたセリフシートをWordの縦書き台本に変換する

1.やりたいこと こんな感じでExcelに書かれたセリフシートを、Wordの縦書き台本に変換します。 <キャラクター紹介> 自己紹介 はじめまして! オレは猫だ! よろしくな。えっ名前? まだ無いんだ、すまない 朝のあいさつ おはよう! 今日も元気そうだな 昼のあいさつ ふぁ~ ちょっと眠いな 夜のあいさつ 疲れた~! 今日はもう終わりにしよう。また明日な! 2.準備 縦書きの収録台本として、今回は配布されている「映画用脚本・シナリオ・ワード・テンプレート」を利用します。 テンプレートを開き、中の文章を全部クリアした後docx形式で保存し直します。 このテンプレートにはスタイルが複数種類登録されていて、今回は「台詞」と「柱・シーン」というスタイルを利用することにします。 importするライブラリ またExcelの読み込みにPythonのopenpyxlを、Wordの読み書きにdocxを使うので、必要に応じてpip installします。 文字列置換も利用するのでimportは下記の3つになります。 import openpyxl import docx import re Wordのリスト番号を拡張する Wordのリスト書式で丸囲い数字を使う場合、①~⑳までしか対応していません。 代替として、行頭に丸囲い数字を入れる関数toCircledを作り、行頭に追加することにします。 ベースはこちらを参考にしました。 これで1~50までは丸囲い数字のリスト風に番号を出力することができます。 #========================================================================================= # 数字を丸囲い数字に変換 #========================================================================================= def toCircled(num): if num <= 0 or num > 50: #1~50以上は丸囲い数字がないので文字列にして戻す return str(num) if num <= 20: return chr(ord('①') + num -1) if num <= 35: return chr(ord('㉑') + num -21) if num <= 50: return chr(ord('㊱') + num -36) 一部文字の変換 また不等号記号は縦書きに対応していないため、山括弧に変換します。 #========================================================================================= # 大なり小なりを山括弧に変換 #========================================================================================= def repSign(str): str = str.replace("<","〈") str = str.replace(">","〉") return str 3.処理 主な処理を書いていきます。 FILENAMEにはExcelのファイル名を、WORD_TEMPLATEにはテンプレートのdocxファイルが指定されています。 表で言う左の部分を太字、右の台詞は装飾なしで書き出します。 #ベースとなるセリフシートを読み込み wb = openpyxl.load_workbook(FILENAME) #ワークシートの分だけ処理する for ws in wb.worksheets: #テンプレートのWordファイル読み込み doc = docx.Document(WORD_TEMPLATE) num = 1 #1行目から5行目までを処理してみる for r in range(1,5): if ws.cell(r,1).value == None: continue #2列目にセリフがある場合 if ws.cell(r,2).value != None: #項目部分は太字 p = doc.add_paragraph() style = p.add_run(toCircled(num) + " " + repSign(ws.cell(r,1).value)) style.bold = True style.font.name = "MS 明朝" p.style = "台詞" #採番をインクリメント num += 1 #セリフを挿入 p = doc.add_paragraph() #行末の句読点を削除し、鍵括弧で挟んで挿入する style = p.add_run(" 「" + re.sub('。$','',repSign(ws.cell(r,2).value)) +"」") style.font.name = "MS 明朝" p.style = "台詞" p = doc.add_paragraph() p.style = "台詞" #セリフがない場合は柱として扱う else: #doc.add_page_break() p = doc.add_paragraph(repSign(ws.cell(r,1).value),style="柱・シーン") #採番をリセット num = 1 #ワークシート名で台本を保存 doc.save(ws.title + '.docx') 4.補足 インデントなどは個々人で使いやすい設定があると思うので、テンプレートのスタイルを変更することをおすすめします。 また表紙などに横書きのものを入れたい場合、Word内で1x1の表を作り、そこにテキストを挿入する方法が簡単です。 (docxではテキストボックスを取得できないようです) 表にテキストを挿入する注意点として、fontで日本語フォントを指定するだけでは反映されないことがあります。 その際は「Python-docxで日本語フォントを使いたい」が参考にしてみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PythonでExcelのセリフシートをWordの縦書き台本に変換する

1.やりたいこと こんな感じでExcelに書かれたセリフシートを、Wordの縦書き台本に変換します。 <キャラクター紹介> 自己紹介 はじめまして! オレは猫だ! よろしくな。えっ名前? まだ無いんだ、すまない 朝のあいさつ おはよう! 今日も元気そうだな 昼のあいさつ ふぁ~ ちょっと眠いな 夜のあいさつ 疲れた~! 今日はもう終わりにしよう。また明日な! 2.準備 縦書きの収録台本として、今回は配布されている「映画用脚本・シナリオ・ワード・テンプレート」を利用します。 テンプレートを開き、中の文章を全部クリアした後docx形式で保存し直します。 このテンプレートにはスタイルが複数種類登録されていて、今回は「台詞」と「柱・シーン」というスタイルを利用することにします。 importするライブラリ またExcelの読み込みにPythonのopenpyxlを、Wordの読み書きにdocxを使うので、必要に応じてpip installします。 文字列置換も利用するのでimportは下記の3つになります。 import openpyxl import docx import re Wordのリスト番号を拡張する Wordのリスト書式で丸囲い数字を使う場合、①~⑳までしか対応していません。 代替として、行頭に丸囲い数字を入れる関数toCircledを作り、行頭に追加することにします。 ベースはこちらを参考にしました。 これで1~50までは丸囲い数字のリスト風に番号を出力することができます。 #========================================================================================= # 数字を丸囲い数字に変換 #========================================================================================= def toCircled(num): if num <= 0 or num > 50: #1~50以上は丸囲い数字がないので文字列にして戻す return str(num) if num <= 20: return chr(ord('①') + num -1) if num <= 35: return chr(ord('㉑') + num -21) if num <= 50: return chr(ord('㊱') + num -36) 一部文字の変換 また不等号記号は縦書きに対応していないため、山括弧に変換します。 #========================================================================================= # 大なり小なりを山括弧に変換 #========================================================================================= def repSign(str): str = str.replace("<","〈") str = str.replace(">","〉") return str 3.処理 主な処理を書いていきます。 FILENAMEにはExcelのファイル名を、WORD_TEMPLATEにはテンプレートのdocxファイルが指定されています。 表で言う左の部分を太字、右の台詞は装飾なしで書き出します。 #ベースとなるセリフシートを読み込み wb = openpyxl.load_workbook(FILENAME) #ワークシートの分だけ処理する for ws in wb.worksheets: #テンプレートのWordファイル読み込み doc = docx.Document(WORD_TEMPLATE) num = 1 #1行目から5行目までを処理してみる for r in range(1,5): if ws.cell(r,1).value == None: continue #2列目にセリフがある場合 if ws.cell(r,2).value != None: #項目部分は太字 p = doc.add_paragraph() style = p.add_run(toCircled(num) + " " + repSign(ws.cell(r,1).value)) style.bold = True style.font.name = "MS 明朝" p.style = "台詞" #採番をインクリメント num += 1 #セリフを挿入 p = doc.add_paragraph() #行末の句読点を削除し、鍵括弧で挟んで挿入する style = p.add_run(" 「" + re.sub('。$','',repSign(ws.cell(r,2).value)) +"」") style.font.name = "MS 明朝" p.style = "台詞" p = doc.add_paragraph() p.style = "台詞" #セリフがない場合は柱として扱う else: #doc.add_page_break() p = doc.add_paragraph(repSign(ws.cell(r,1).value),style="柱・シーン") #採番をリセット num = 1 #ワークシート名で台本を保存 doc.save(ws.title + '.docx') 4.補足 インデントなどは個々人で使いやすい設定があると思うので、テンプレートのスタイルを変更することをおすすめします。 また表紙などに横書きのものを入れたい場合、Word内で1x1の表を作り、そこにテキストを挿入する方法が簡単です。 (docxではテキストボックスを取得できないようです) 表にテキストを挿入する注意点として、fontで日本語フォントを指定するだけでは反映されないことがあります。 その際は「Python-docxで日本語フォントを使いたい」が参考にしてみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

最近見つけたクールなPythonライブラリ6選

本記事は、Dhilip Subramanian氏による「6 Cool Python Libraries That I Came Across Recently」(2021年7月12日公開)の和訳を、著者の許可を得て掲載しているものです。 最近見つけたクールなPythonライブラリ6選 機械学習のためのすごいPythonライブラリ Image by Free-Photos from Pixabay はじめに Pythonは機械学習に不可欠な要素で、ライブラリは作業をより単純にしてくれます。最近、MLのプロジェクトに取り組んでいる時に、素晴らしいライブラリを6つ見つけました。ここでは、それを紹介します。 1. clean-text clean-textは本当に素晴らしいライブラリで、スクレイピングやソーシャルメディアデータを処理する時にまず使うべきものです。最も素晴らしい点は、データをクリーンアップするために長く凝ったコードや正規表現を必要としないことです。 いくつかの例を見てみましょう。 インストール !pip install cleantext 例 #Importing the clean text library from cleantext import clean # Sample text text = """ Zürich, largest city of Switzerland and capital of the canton of 633Zürich. Located in an Al\u017eupine. ([https://google.com](https://google.com/)). Currency is not ₹""" # Cleaning the "text" with clean text clean(text, fix_unicode=True, to_ascii=True, lower=True, no_urls=True, no_numbers=True, no_digits=True, no_currency_symbols=True, no_punct=True, replace_with_punct=" ", replace_with_url="", replace_with_number="", replace_with_digit=" ", replace_with_currency_symbol="Rupees") 出力 上記から、Zurichという単語にUnicod(「u」の文字がエンコードされている)、ASCII文字(Al\u017eupine)、ルピー通貨記号、HTMLリンク、句読点を含むことがわかります。 clean関数では、必要なASCII、Unicode、URL、数値、通貨、句読点を指定するだけです。または、置換パラメータに置き換えることもできます。例えば、ルピー記号をRupeesに変更しました。 正規表現や長いコードは全く必要ありません。特に、スクレイピングやソーシャルメディアデータからテキストをクリーンアップしたい場合は、非常に便利なライブラリです。必要に応じて、引数をすべて組み合わせるのではなく、個別に渡すこともできます。 詳細については、GitHubリポジトリを確認してください。 2. drawdata drawdataは、もう1つの便利なpythonライブラリです。MLの概念をチームに説明しなければならない状況に、何回遭遇しましたか?データサイエンスはチームワークが大事なので、よくあることでしょう。このライブラリは、Jupyterノートブックにデータセットを描くのに役立ちます。 個人的には、MLの概念をチームに説明する時に、このライブラリを使うのはとても楽しかったです。このライブラリを作成した開発者に賛辞を送ります! drawdataは、4つのクラスの分類問題のみを対象としています。 インストール !pip install drawdata 例 # Importing the drawdata from drawdata import draw_scatter draw_scatter() 出力 著者による画像 draw_Scatter()を実行すると、上記の描画ウィンドウが開きます。明らかに、A、B、C、Dの4つのクラスがあります。任意のクラスをクリックして、好きな点を描画できます。各クラスは、描画中に異なる色を描画します。データをcsvまたはjsonファイルとしてダウンロードするオプションもあります。また、データをクリップボードにコピーして、下記のコードから読み取ることもできます。 #Reading the clipboard import pandas as pd df = pd.read_clipboard(sep=",") df このライブラリの限界の1つは、4つのクラスで2つのデータポイントしか提供しないことです。しかしそれ以外の点では、このライブラリを使う価値は十分あります。 詳細については、GitHubリンクを確認してください。 3. Autoviz matplotlibをって探索的データ分析をしていた時のことは一生忘れないでしょう。多くの単純な可視化ライブラリがありますが、最近、1行のコードであらゆるデータセットを自動的に可視化するAutovizを知りました。 インストール !pip install autoviz 例 この例では、IRISデータセットを使用しました。 # Importing Autoviz class from the autoviz library from autoviz.AutoViz_Class import AutoViz_Class #Initialize the Autoviz class in a object called df df = AutoViz_Class() # Using Iris Dataset and passing to the default parameters filename = "Iris.csv" sep = "," graph = df.AutoViz( filename, sep=",", depVar="", dfte=None, header=0, verbose=0, lowess=False, chart_format="svg", max_rows_analyzed=150000, max_cols_analyzed=30, ) 上記のパラメータはデフォルトです。詳細については、こちらを確認してください。 出力 著者による画像 たった1行のコードで、全ビジュアルを確認し、EDAを完成させることができます。多くの自動可視化ライブラリがありますが、特にこのライブラリに慣れ親しむのはとても楽しかったです。 4. Mito みんなExcelが好きですよね?Excelはデータセット探索の最も簡単な最初の方法の1つです。Mitoに出会ったのは数ヶ月前ですが、使ってみたのはつい最近で、とても気に入りました! これはJupyter-lab拡張Pythonライブラリで、表計算機能を追加するGUIをサポートしています。csvデータを読み込み、データセットをスプレッドシートとして編集すると、自動的にPandasコードを生成します。とてもクールです。 Mitoを紹介するには、ブログ1記事を要します。しかし、今日はあまり詳しく説明しません。代わりに、簡単なタスクのデモを紹介します。詳細については、こちらを確認してください。 インストール #First install mitoinstaller in the command prompt pip install mitoinstaller # Then, run the installer in the command prompt python -m mitoinstaller install # Then, launch Jupyter lab or jupyter notebook from the command prompt python -m jupyter lab インストールの詳細については、こちらを確認してください。 # Importing mitosheet and ruuning this in Jupyter lab import mitosheet mitosheet.sheet() 上記のコードを実行すると、jupyter labでmitosheetが開きます。私はIRISデータセットを使用しています。まず、2つの新しい列を作成します。1つはがく片長、もう1つはがく片幅の合計です。次に、平均がく片長の列名を変更します。最後に、平均がく片長の列のヒストグラムを作成します。 この手順を実行すると、コードが自動的に生成されます。 出力 著者による画像 上記の手順で、以下のコードが生成されました。 from mitosheet import * # Import necessary functions from Mito register_analysis('UUID-119387c0-fc9b-4b04-9053-802c0d428285') # Let Mito know which analysis is being run # Imported C:\Users\Dhilip\Downloads\archive (29)\Iris.csv import pandas as pd Iris_csv = pd.read_csv('C:\Users\Dhilip\Downloads\archive (29)\Iris.csv') # Added column G to Iris_csv Iris_csv.insert(6, 'G', 0) # Set G in Iris_csv to =AVG(SepalLengthCm) Iris_csv['G'] = AVG(Iris_csv['SepalLengthCm']) # Renamed G to Avg_Sepal in Iris_csv Iris_csv.rename(columns={"G": "Avg_Sepal"}, inplace=True) 5. Gramformer Gramformerはもう1つの印象的なライブラリです。生成モデルに基づいており、文の文法を修正するのに役立ちます。このライブラリには、検出、強調表示、修正の3つのモデルがあります。検出はテキストの文法エラーを識別し、強調表示は品詞のミスをマークし、修正はエラーを修正します。Gramformerは完全なオープンソースで、まだ初期段階です。ただし、文レベルでのみ動作し、64文字長の文章で学習されているため、長い段落には適しません。 現在のところ、修正と強調表示のモデルが機能しています。いくつかの例を見てみましょう。 インストール !pip3 install -U git+https://github.com/PrithivirajDamodaran/Gramformer.git Gramformerインスタンス化 gf = Gramformer(models = 1, use_gpu = False) # 1=corrector, 2=detector (presently model 1 is working, 2 has not implemented) 例 #Giving sample text for correction under gf.correct gf.correct(""" New Zealand is island countrys in southwestern Paciific Ocaen. Country population was 5 million """) 出力 著者による画像 上記の出力から、文法やスペルミスまで修正していることが分かります。本当に素晴らしいライブラリで、機能も非常に優れています。ここでは強調表示を試していませんが、詳細については、GitHubドキュメントで確認してください。 6. Styleformer Gramformerでの良い経験から、もっと優れたライブラリを探すようになりました。そのようにして見つけたのが、この非常に魅力的なライブラリStyleformerです。GramformerもStyleformerもPrithiviraj Damodaran氏が作成したもので、どちらも生成モデルに基づいています。このライブラリをオープンソース化した作者に賛辞を送ります。 Styleformerは、カジュアルな文章からフォーマルな文章へ、フォーマルな文章からカジュアルな文章へ、能動態から受動態へ、受動態から能動態への変換をサポートします。 いくつかの例を見てみましょう。 インストール !pip install git+https://github.com/PrithivirajDamodaran/Styleformer.git Styleformerインスタンス化 sf = Styleformer(style = 0) # style = [0=Casual to Formal, 1=Formal to Casual, 2=Active to Passive, 3=Passive to Active etc..] 例 # Converting casual to formal sf.transfer("I gotta go") # Formal to casual sf = Styleformer(style = 1) # 1 -> Formal to casual # Converting formal to casual sf.transfer("Please leave this place") # Active to Passive sf = Styleformer(style = 2) # 2-> Active to Passive # Converting active to passive sf.transfer("We are going to watch a movie tonight.") # passive to active sf = Styleformer(style = 2) # 2-> Active to Passive # Converting passive to active sf.transfer("Tenants are protected by leases") 上記の出力を見ると、正確に変換されています。私は、特にソーシャルメディアへの投稿の分析で、カジュアルからフォーマルへ変換するのに使いました。詳細については、GitHubを確認してください。 おわりに 先に挙げたライブラリのいくつかはよく知っているかもしれませんが、GramformerやStyleformerなどは最近のものです。これらは非常に過小評価されていますが、知っておく価値があります。私の時間を大幅に節約してくれ、NLPプロジェクトでよく使用していました。 お読みいただきありがとうございます。もし追加があれば、気軽にコメントをお寄せください! 以前の記事「データサイエンスのためのクールなPythonライブラリ5選」もおすすめです。 翻訳協力 この記事は以下の方々のご協力により公開する事ができました。改めて感謝致します。 Original Author: Dhilip Subramanian (https://www.linkedin.com/in/dhilip-subramanian-36021918b/) Original Article: 6 Cool Python Libraries That I Came Across Recently Thank you for letting us share your knowledge! 選定担当: @gracen 翻訳担当: @gracen 監査担当: - 公開担当: @gracen ご意見・ご感想をお待ちしております 今回の記事はいかがでしたか? ・こういう記事が読みたい ・こういうところが良かった ・こうした方が良いのではないか などなど、率直なご意見を募集しております。 頂いたお声は、今後の記事の質向上に役立たせて頂きますので、お気軽に コメント欄にてご投稿ください。Twitterでもご意見を受け付けております。 皆様のメッセージをお待ちしております。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Python】毎日Pythonを自動実行するタスクスケジューラを設定してみた

はじめに Pythonを使って様々な作業を自動化を進めている方、 「Pythonの実行を自動化」しないと毎日Pythonのプログラムをクリックしないといけません。 例えば先日書いた以下の記事も同様です。 そこでWindows10の場合は、標準で「タスクスケジューラ」というアプリが入っていますのでこれを活用します。 意外設定にとクセがあるので、私がいま成功している設定をお伝えしますのでご参考になれば幸いです。 環境 ・python3.7 ・windows10 タスクスケジューラ 私が設定しているタスクスケジューラの設定を記載します。 ユーザ名などはご自身のアカウントに変更をお願いします。 1.[全般]タブ 名前:任意の名前にします。(例:HP_CHECK) 説明:タスクの説明を記載します。(例:abc幼稚園のHPに更新情報がないかチェックします。) セキュリティオプション: タスク実行時に使うユーザアカウント:管理者権限をもっているユーザを指定します。(例:hirockio)  ●ユーザーがログオンしているかどうかにかかわらず実行する  ☑最上位の特権で実行する 2.[トリガー]タブ 実行するスケジュールを記載します。 設定:●毎日 開始:本日日付以降を指定します。(例:2020/04/01) 時間:毎日実行する時間を指定します。(例:8:43:00) 間隔:実行間隔を指定します。(例:1日) 詳細設定:☑有効 にチェックをいれます。 3.[操作]タブ 実行するPythonのプログラムを指定します。 操作:プログラムの開始 設定:プログラム/スクリプト Pythonがインストールされた場所を指定します。 例:C:\Users\hirockio\AppData\Local\Programs\Python\Python37\python.exe 引数の追加:プログラム名を記載します。(例:HP.py) 開始:配置したプログラムの場所を指定します。(C:\Python\) 4.[条件]タブ 電源:☑タスクの実行するためにスリープを解除する 5.[設定]タブ ☑タスクを要求時に実行する ☑タスクが停止するまでの時間 [3日間] ☑要求時に実行中のタスクが終了しない場合、タスクを強制的に停止する 最後に PCがシャットダウンしているとタスクが実行されませんが、スリープ状態であればタスクは実行されます。「電源とスリープ設定」でタスクが実行される時間にPCがシャットダウンされない設定になっているかご確認下さい。 ご参考になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python初学者の備忘録 コレクションについて

←目次へ python,Qiita初心者なので、備忘録として記載していきます。 なにせ初心者なので、知識不足はご理解ください。 知識を深めながら追記していきたいと思います。 コレクションとは 複数のデータを格納することから「コレクション」「コンテナ」などと呼ぶこともある また、そのうち「リスト」と「タプル」はシーケンス型オブジェクトとも呼ぶこともある ※「range」「文字列」もそれにあたる オブジェクト生成後に要素を変更できる:mutableオブジェクト オブジェクト生成後に要素を変更できない:immutableオブジェクト 各コレクションの違い データ型 変更可否 要素の順序 インデックス 説明 リスト 〇 〇 〇 任意の型のデータを格納できる タプル × 〇 〇 任意の型のデータを格納できる 辞書 〇 × × キーと値の組で表されるデータを格納する 集合 〇 × × 重複の無いリストを格納する リスト型 タプル型 辞書型(連想配列) 集合型 同じ要素数のシーケンスの比較演算 タプルやリストなどのシーケンスオブジェクトは比較演算できる シーケンス同士の比較は、先頭の要素から順番に同じインデックス同士の値を比較して、先に小さい値となったシーケンスが小さい値となる # -- リストの場合 -- >>> list1 = ['a', 'b', 'c'] >>> list2 = ['a', 'b', 'd'] >>> print(list1 <= list2) True >>> list3 = ['a', 'b', 'c'] >>> list4 = ['a', 'b', 'b'] >>> print(list3 <= list4) False # -- タプルの場合 -- value1 = (1, 2, 3, 4) value2 = (1, 2, 3, 5) print(value1 < value2) True value3 = (1, 2, 3, 4) value4 = (1, 2, 3, 3) print(value3 < value4) False 異なる要素数のシーケンスの比較演算 比較するシーケンス同士の長さが異なる場合、短いシーケンスの要素と長いシーケンスの要素を比較してすべて等しければ、短い要素のほうが小さい値となる # -- リストの場合 -- >>> list1 = ['a', 'b', ] >>> list2 = ['a', 'b', 'C'] >>> print(list1 <= list2) True # -- タプルの場合 -- value1 = (1, 2, 3) value2 = (1, 2, 3, 4) print(value1 < value2) True 異なるコレクションの比較演算はできない list1 = [1, 2, 3] value2 = (1, 2, 3) print(list1 <= value2) # TypeError: '<=' not supported between instances of 'list' and 'tuple' # 型が違うためエラーになる 辞書型や集合型は比較演算できない
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python初学者の備忘録 初級編④比較演算子について

←前項 比較演算子 基本 2つの式や値を比較し、boolを返す 以下の演算子がある 記号 計算 記号 計算 記号 計算 <= 以下 == 等しい != 等しくない > より大きい < より小さい >= 以上 出力結果 >>> 1 == 1 #>>> True >>> 1 != 1 #>>> False >>> 1 == '1' #>>> False 型が違うのでFalseになる >>> int('1') #>>> 1 int型になる >>> 1 == int('1') #>>> True int型に変換したのでTrueになる >>> 2 > 1 #>>> True >>> 2 < 1 #>>> False # 論理積 and すべての条件がTrueの場合Trueになる >>> 5 <= 6 and 5 >= 0 #>>> True >>> 5 <= 6 and 5 <= 0 #>>> False # 論理和 or いずれかの条件がTrueの場合Trueになる >>> 5 <= 6 or 5 <= 0 #>>> True >>> 5 == 6 or 5 <= 0 #>>> False >>> 1 < 6 < 10 #>>> True >>> 1 < 6 > 10 #>>> False 次項→
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python初学者の備忘録 初級編③print関数について

←前項 print関数の基本 基本 print(値)で「値」を出力できる ()の中を「,」で区切る事で複数の値を出力できる ()の中で演算も行うことが出来る 出力結果 print(1) # >>>1 print(0.100100) #>>> 0.001 print('0.100100') #>>> 0.100100 print('Hello') #>>> Hello print(1., 1) #>>> 1 1 print('a', 'b', 'c') #>>> a b c print(1 + 2) #>>> 3 print('テストの点数は' + 100 + '点です') # 文字と数字は結合出来ないのでエラー print('テストの点数は' + '100' + '点です')または print('テストの点数は' + str(100) + '点です') # >>>テストの点は100点です 次項→
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python 初歩の初歩①型について

データ型とは 基本 int型(整数型) 例:「1」「-5」など float型(浮動小数型) 例:「0.1」 str型(文字列型) 例:「あ」 bool型(ブール型) 例:「True」「False」 出力結果 展開 sample.py number = 1 number2 = 1.0 greeting = 'こんにちは'または"こんにちは" is_ok = True print(number,type(number)) # >>>1 <class 'int'> print(number2 ,type(number)) # >>>1.0 <class 'float'> print(greeting ,type(number)) # >>>こんにちは <class 'str'> print(is_ok ,type(number)) # >>>True <class 'bool'> #不等式 print(2 > 1) # >>>True print(2 < 1) # >>>False ※type()型を返す 数値型 基本 + int型とfloat型の2つからなる + 以下の演算子を使うことが可能 記号 計算 記号 計算 記号 計算 + 足し算 * 掛け算 // 割り算(切り捨て) - 引き算 / 割り算 % 割ったあまり ** べき乗 出力結果 展開 >>> 5 / 3 1.66666666666666667 >>> 5 % 3 2 >>> 5 * 5 * 5 * 5 * 5 * 5 or >>> 5 ** 6 15625 >>> 3 + 2.0 5.0 >>> 5 - 2.3 2.7 #int型とfloat型で計算した場合float型になる >>> int(2.7) 2 #int型になる >>> str(2.7) '2.7' #str型になる >>> bool(1) True >>> bool(0) False #0以外はTrueになる int型とfloat型で計算した場合float型になる 文字列型 「¥n」「”””」で改行 数値型と同様に「+」「*」で文字列の連結や繰り返しが可能 --文字列インデックス-- 出力結果 展開 >>> 'Mika' 'Mika' >>> 'Mika'[0] 'M' >>> 'Mika'[1] 'i' >>> 'Mika'[2] 'k' >>> 'Mika'[3] 'a' >>> 'Mika'[4] #4番目の文字は無いためエラー >>> 'Mika'[-1] 'a' >>> 'Mika'[-2] 'k' >>> 'Mika'[-3] 'i' >>> 'Mika'[-4] 'M' #-は最後から数えた文字 --文字列のスライス-- 出力結果 展開 >>> 'English'[2:5] 'gli' #3文字目から6文字目まで >>> 'English'[2:] 'glish' #3文字目から最後まで >>> 'English'[:4] 'Engl' #4文字目まで --文字列長さを調べる-- 出力結果 展開 #len()関数 文字長を返す >>> len('English') 7 #count()メソッド 文字列に含まれている数を返す >>> 'English Shool'.count(o) 2 len()関数:文字長を返す count()メソッド:文字列に含まれている数を返す 次項→
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python初心者 初級編②変数について

←前項 変数について 基本 1など数字からの変数は宣言出来ない Trueやifなどの予約語は使用できない コードは上からの処理なので変数は上書きされる 他言語のように宣言時に型を指定する必要がない。 代入するたびに型が変わる。 そのため暗黙的なキャストが発生しないように注意する。 出力結果 >>> name = 'Mika' >>> name #>>> 'Mika' >>> name = 'Freddy' >>> name #>>> 'Freddy' >>> a = 5 >>> b = 10 >>> print(a, b) #>>> 5 10 # 一度に代入する事も可能 >>> a, b = b, a >>> print(a, b) #>>> 10 5 # 一度に宣言する事も可能 >>> c, d = 20, 30 >>> c #>>> 20 次項→
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

python初学者の備忘録 初級編②変数について

←前項 変数について 基本 1など数字からの変数は宣言出来ない Trueやifなどの予約語は使用できない コードは上からの処理なので変数は上書きされる 他言語のように宣言時に型を指定する必要がない 代入するたびに型が変わる そのため暗黙的なキャストが発生しないように注意する 出力結果 >>> name = 'Mika' >>> name #>>> 'Mika' >>> name = 'Freddy' >>> name #>>> 'Freddy' >>> a = 5 >>> b = 10 >>> print(a, b) #>>> 5 10 # 一度に代入する事も可能 >>> a, b = b, a >>> print(a, b) #>>> 10 5 # 一度に宣言する事も可能 >>> c, d = 20, 30 >>> c #>>> 20 次項→
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

緊急避妊にかかる対面診療が可能な産婦人科医療機関等の一覧をCSVに変換

スプレッドシート camelotだと遅いのと変換できない県があったのでpdfplumberで変換 とりあえず変換のみ import pathlib from urllib.parse import urljoin import requests from bs4 import BeautifulSoup import pdfplumber import pandas as pd headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" } def fetch_soup(url, parser="html.parser"): r = requests.get(url, headers=headers) r.raise_for_status() soup = BeautifulSoup(r.content, parser) return soup def fetch_file(url, name, dir="."): p = pathlib.Path(dir, f"{name}.pdf") p.parent.mkdir(parents=True, exist_ok=True) r = requests.get(url) r.raise_for_status() with p.open(mode="wb") as fw: fw.write(r.content) return p url = "https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/0000186912_00002.html" soup = fetch_soup(url) dfs = [] for i in soup.select("ul.m-listLink--hCol2 > li > a"): pref = i.get_text() print(pref) link = urljoin(url, i.get("href")) p = fetch_file(link, pref) with pdfplumber.open(p) as pdf: for page in pdf.pages: table = page.extract_table() df_tmp = pd.DataFrame(table) row, col = df_tmp.shape if col == 8: df_tmp.insert(0, "有無", "") df_tmp.set_axis( [ "公表の希望の有無", "施設名", "郵便番号", "住所", "電話番号", "ウェブサイトURL", "産科、婦人科又は産婦人科の標榜の有無", "医療機関における緊急避妊にかかる対面診療への対応可能時間帯", "常時の緊急避妊薬の在庫の有無", ], axis=1, inplace=True, ) dfs.append(df_tmp) df0 = pd.concat(dfs).reset_index(drop=True) df0 df1 = df0.copy() df1[df1["施設名"].isin(["基本情報", "施設名"])].to_csv("kakunin.csv", encoding="utf_8_sig") df1.shape df2 = df1[~df1["施設名"].isin(["基本情報", "施設名"])].copy().reset_index(drop=True) df2.shape df2["施設名"] = df2["施設名"].str.replace("\n", "") df2["住所"] = df2["住所"].str.replace("\n", "") df2["ウェブサイトURL"] = df2["ウェブサイトURL"].str.replace("\n", "") df2 df2.to_csv("list.csv", encoding="utf_8_sig")
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Minecraftで夏休みの自由研究?・・・の手伝い

2021年8月27日現在・・息子の自由研究がまだ終わっていない・・・ 何かないかとネットで探していたところこちらのサイトを発見。 数学の教科書を開くと夏休み明けから関数を習うらしい。。 ならばMinecraftで関数グラフを描いてみようということにした。 MinecraftのForgeは既に使っているし(というよりバニラをもう何年もやっていない)息子も自分でお気に入りのMODを探してきて遊んでいる。 とは言っても息子がマイクラでプログラミングを始めるまでの全手順解説書を読みながらプログラムを実行できるまで待っていたら年が明けてしまいそうなのでプログラミング環境の設定は私が行った。 今回は関数の値を変化させてみてグラフがどうなるかを確かめることが目的なのでPythonの文法などは無視して、下記プログラムの赤枠部分の変更と実行ボタンの押下を息子が担当。 最初はMinecraftで明るい時間帯に石ブロックでグラフを描いてみましたが見難いのでMinecraftのコマンド/time set nightで夜にして、グラフを描くブロックは息子の提案でシーランタンとジャックオーランタンで光るようにした。 簡単なグラフを描いてみる $ y = x $ 描けた! $ y = x + 5 $ 最初のグラフとの違いがわかり難いが、グラフの始点が地面から+5ブロック浮いているのがわかる。 反比例(だっけ?)のグラフ $ y = \frac{50}{x} $ 二次関数のグラフ $ y = x^2 $ 整数でグラフを描いているからかなんか教科書にのグラフと雰囲気が違う・・ $ y = \frac{x^2}{10} $ $ \frac{1}{10} $ したらいい感じに描けた 色を変えてマイナスの二次関数のグラフ(呼び方あってるのかな?) $ y = - x^2 $ プラスとマイナスの二次関数グラフ $ y1 = x^2, y2 = -x^2 $ ↑ のグラフは荒いので$ \frac{1}{10} $してみる。 $ y1 = \frac{x^2}{10}, y2 = - \frac{x^2}{10} $ いい感じ おまけ 正面からだけ見てもつまらない・・・せっかくのMinecraftなので視点を移動してグラフを確認。 近くで見るとシーランタンとジャックオーランタンでグラフが描かれていることがよくわかる。 地上にはスライムなどのMobもちらほら・・ レポート作成 プログラムとMinecraftのグラフ結果を印刷してペタペタ。 自由研究レポートの表紙は息子が書き書きして完成 お疲れさまでした
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsマンにとってPandasのDataFrame型がモヤモヤする理由

PandasのDataFrame型はモヤモヤする 当方、元々Rails歴3年で、最近Kaggleを始めた超初心者なのですが、Railsの経験が活かされる場面もあれば、逆にRailsの経験がバイアスになり混乱する場面もあります。入門してまず躓いたのは、PandasのDataFrame型です。特にdf['name']やdf.iloc[0]とやらで混乱してしまいました。 RailsとPandas テーブルデータの操作の違い 例えば、次のようなテーブルデータからオブジェクトを作成し、1行目・1列目を取り出す場合のコードの違いを比較します。 id name 1 田中太郎 2 佐藤花子 3 山田一郎 PandasのDataFrame型 data = { 'id': [1, 2, 3], 'name': ['田中太郎', '佐藤花子', '山田一郎'] } users = pd.DataFrame(data) # 1行目を取り出したいとき users.iloc[0] # 1列目を取り出したいとき users['id'] RailsのActive Record data = [ {id: 1, name: '田中太郎'}, {id: 2: name: '佐藤花子'}, {id: 3: name: '山田一郎'}, ] users = User.new(data) # 1行目を取り出したいとき users[0] # 1列目を取り出したいとき users.select('id') 何が違うのか? PandasもRailsも、テーブルのデータを操作するという点で共通ですが、決定的に違う点があります。それはズバリ、 Pandasは列でデータを区切るが、 Railsは行でデータを区切る という違いになります。 それぞれのdataの型を見比べればさらに明らかになります。 Pandasでは辞書型になっていますが、Railsでは配列型になっています。 実はPandasがusers['id']と書くのは、Pandasだから(あるいはPythonだから)ではなく、辞書型だから当然のことなのです。 なぜ違うのか?(私見) どちらもテーブルのデータを操作するという点で共通ですが、なぜPandasでは列でデータを区切り、Railsは行でデータを区切るのでしょうか? これは公式の見解ではなく、私見になります。 それは単純に、PandasとRailsで用途が違うから だと思います。 Pandasの用途はデータ分析なので、行よりも列を柔軟に扱いたい →データ分析では、列ごとに何かしらの処理をしたいことが多いです。例えばある列の平均値を算出したり、ある列の欠損値を埋めたりなど。逆に分析対象のデータの行数が増減したり、行ごとに抽出したりするシーンは比較的少ないのだと思います。なので列ごとにデータを区切ったほうが都合が良いです。 Railsの用途はWeb開発なので、列よりも行を柔軟に扱いたい →一方、Web開発では行ごとに何かしらの処理をしたいことが多いです。where文である条件に合致する行だけを抽出したり、行の新規追加、削除、更新など。逆にテーブルの列が増減したりは比較的少ないと思います。なので行ごとにデータを区切ったほうが都合が良いです。 PandasのDataFrameはスバラシイ 以上のように理解してから、PandasのDataFrame型と仲良くなれた気がします。公式の見解ではありませんが、少しでもPandas習得の助けになれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む