LoginSignup
55
88

More than 5 years have passed since last update.

Python3で色々する時の個人的Tips

Last updated at Posted at 2017-07-27

概要

VSCodeでPython3で機械学習とかデータマイニング的なことをする時に得られた知見をメモしていく。

読み辛いのは重々承知。

随時更新。

Python3オンリーな場合の開発環境構築の個人的ベストプラクティス

Python3 + venv + VSCode + macOS な開発環境の構築 - Qiita

作図ライブラリ比較

Jupyter-notebook の作図ライブラリ比較 - Qiita

インタラクティブな可視化

ipywidgetsとBokeh使ってインタラクティブな可視化をする - Qiita

VSCodeのjupyter extensionでipywidgetsをしようとすると、スクリプト周りが読めないようなので使えない。
support for ipython/jupyter widgets · Issue #21 · DonJayamanne/vscodeJupyter
大人しくブラウザのJupyterでやろう

サンプル

numpy使ってたらpylintがhas no ~のエラーが出る時はVSCodeのsettings.jsonに

    "python.linting.pylintArgs": [
        "--extension-pkg-whitelist=numpy"
    ]

Pylint で no-member エラーを出なくする - Qiita

k-meansした時に ValueError: n_samples=1 should be >= n_clusters=3 なエラーが出る理由

必要となるデータは2次元である必要があるので、このブログではappendしていて非効率なので、sample_data.iloc[:, 0:1]のようにするといい。

これで抽出できるのは1列目であり、sample_data.iloc[:, 0]とした時と変わらないが、0:1とすることで2次元で表されることになるようで、上記のエラーは出なくなる

機械学習・クラスタリングを理解するまで6日目 - ITの隊長のブログ

df = pd.DataFrame()df.append(df2) しても dfには追加されない。

df = df.append(df2) とすべし

python - Appending to an empty data frame in Pandas? - Stack Overflow

:の後ろに型名を書くおくと(Type Hints)、IntelliSenseしてくれるようになる

ただしType Hintsは単なるコメントと同義なようなので、合ってない型のオブジェクトを渡してもlinterは怒らないし、実行するまで型チェックはされない

Pythonではじまる、型のある世界 - Qiita

クラスメンバのスコープ

Pythonのクラスメンバのスコープまとめ - Qiita

pandasのデータをいい感じに取り出したい時

Python pandas データのイテレーションと関数適用、pipe - StatsFragments

listをforeachするときにindexも欲しい時

リストのインデックス (enumerate) - Python入門から応用までの学習サイト

dataframeの中身の型を変換したい時

Pandas: Converting to numeric, creating NaNs when necessary

pip-compileとpip-syncの組み合わせ良さげ

pip関連ツールでPythonのパッケージ管理を楽にする - Qiita

DataFrameの連結や結合した時の図解

シンプルに縦に結合したい時はappend、横に結合したい時はjoin

Python pandas 図でみる データ連結 / 結合処理 - StatsFragments

pandasのdataFrameをprintした時に量が多かったら省略されてしまうが、任意に設定すれば全表示とかできる

pd.set_option("display.max_rows", 10)

pandasで表示が省略されるのを防ぐ - 仕事中の問題と解決メモ。

多次元のlistをソートする場合にはsortのkeyをlambda

【Python】ソート#多次元リストのソート

データ構造別のソートの仕方

Python sortのまとめ (リスト、辞書型、Series、DataFrame) - Qiita

isortを使えばimportをいい感じにreformatしてくれます

code-python-isort - Visual Studio Marketplace

%sql select * from hoge

とか書くだけていい感じにDataFrameとかにも突っ込めるjupyterのextention
ipython-sql

VSCodeでJupyterなpyをipynbに変換するツール作った - Qiita

VSCodeでJupyterなpyをipynbに変換するツール作った - Qiita

前者のappendはIntelliSenseが働いてappendって出てくるが、後者のは出てこない

tttt = pd.DataFrame()
tttt.append(None)
tttt = df[["label"]]
tttt.append(None)

これは引数の型が分からないからなので、assert isinstance とかを使ってdf[[“label”]]の後に型を明示してあげれば、appendはIntelliSenseで出てくる

IntelliSense に仕事してもらう Python の書き方 - アジョブジ星通信

grouperとても便利

Python pandas アクセサ / Grouperで少し高度なグルーピング/集計 - StatsFragments

時系列データを1sec毎とか1日毎とかでグルーピングしたりもできる

.replace("hoge", "toHoge") で置換できるのは対象の文字列に対してだけだが、

.replace(".*", "+1", regex=True) みたいに正規表現でもいける

機械学習の超初心者が、みんなが良いと言う記事を読んでまとめてみた - Qiita

機械学習の超初心者が、みんなが良いと言う記事を読んでまとめてみた - Qiita

confusion matrixを出したくなったらこんな感じですぐできる

from sklearn.metrics import confusion_matrix

test_label_lb = []  # 正解ラベル
p_label = []  # 推定ラベル

cmx_data = confusion_matrix(y_true=test_label_lb, y_pred=p_label)
labels = ["A", "B", "C"]
df_cmx = pd.DataFrame(cmx_data, index=labels, columns=labels)

開発者がビッグデータ分析にPythonを使う時によくやる間違い | プログラミング | POSTD

jupyterで地下はともかく地図表示できる

Folium

import folium
m = folium.Map(location=[33.763, -84.392], zoom_start=17)
folium.Marker(
    location=[33.763006, -84.392912],
    popup='World of Coca-Cola'
).add_to(m)
m

やはりラムダ使う方がスマートか

Python3におけるmap/filterの使い方 - どこかに向かうらしい話

いい感じのplot例

Python pandas プロット機能を使いこなす - StatsFragments

mapやfilterで返してくるのはiteratorなので

list()などで中身出しちゃうとiteratorが進んでしまう

num_map = map(lambda n: n + 1, np.random.random(1000))
print(list(num_map)) # ここでは値でる

num_filter = filter(lambda n: n > 0.5, np.random.random(1000))
print(list(num_filter)) # ここでは値でる

print(list(num_map)) # ここではもうでない
print(list(num_filter)) # ここではもうでない

dictのvalueがmaxなもののkeyを見つけたいなら1行でいける

max(dic, key=lambda i: dic[i])

パスの操作はpathlibが簡単

Python3.4以降ならos.pathはさっさと捨ててpathlibを使うべき

from pathlib import Path
LOG_DIR = "/Users/your_name/log"

Path(LOG_DIR).joinpath("log.json") #それか Path(LOG_DIR) / "log.json"
# PosixPath('/Users/your_name/log/log.json') となる

Path(LOG_DIR).joinpath("log.json").exists() 
# False

multiprocessing使ってマルチプロセスで処理

pythonでマルチコア並列処理をする方法

rangeで適当に渡せばいいので簡単

いろいろあるグラフ描画ツールのラッパーHoloViews

Pythonの可視化ツールはHoloViewsが標準になるかもしれない
HoloViewsの基本的なグラフをワンライナーで

進捗バーの表示

Pythonで進捗バーを表示する(tqdm)

iterableのオブジェクトを渡せば秒速何iterate?で進捗しているのかも分かったりするのでいい目安になる

matplotlibでsavefigしたらラベルがはみ出る時がある

bbox_inches = "tight"とかそれ系のやつ

フォントデカくしたりしたり、横長とか縦長グラフを作るとsavefigでラベルがはみ出ることがあるので.savefig("test.png", bbox_inches="tight")とすると綺麗に出る

実行時間を測りたい

Jupyter Notebook > %timeit range(100) > 処理時間の計測 > %%timeit > 複数文の処理時間の計測
IPythonでコードの実行時間を測る話

Jupyterでなら%time func()でfuncの実行時間が取れるが、割とブレる
%timeit func()にすると何回か実行して測ってくれる

VSCodeのjupyter extensionでは%%timeitを認識しないので複数行を評価する場合はVSCodeのJupyterでは無理っぽい(まぁ関数にすればいい)

そのDataFrameにNaNあるのか

pandas DataFrame内にNaNありますか?
df.isnull().values.any()が覚えやすいし早いので良さげだが、型によっても変わってくるのでお試しあれ

Pandasで高速に処理するためのtips

Python pandas パフォーマンス維持のための 3 つの TIPS

pythonVSCodeでautocomplete遅い問題

Slow auto complete speed for custom modules python #903
Slow autocompletion/formatting #581

VSCodeのsettings.jsonに以下のように追記するとpreloadしてくれる。

"python.autoComplete.preloadModules": [
    "pandas",
    "numpy",
    "matplotlib"
]

これにより、pandas.DataFrame()とかのsuggestは早くなってる気がするけど、型推論が必要な場面では変わらない気がする。
assert isinstanceで明示してあげると早くなるけど、一々やってられん...

df = func_something()
df.sum() #ここではsumが出るの遅い

assert isinstance(df, pd.DataFrame)
df.sum() #ここではsumはすぐ出る

JupyterでPoolでマルチプロセスな処理したらゾンビ大量発生問題

IPythonでmultiprocessingを使ってたらゾンビ化するとき

#p = Pool()
p.terminate()

明示的に殺すか、

with Pool() as p:
    results = p.map(func, range(0, 100))

withを使う

filterやmapを2重にしてlambdaの変数を参照するとpylintがE0602で怒る

list_prefixにあるprefixと一致するものをlist_abから見つける場合(この例はあまりうまい例じゃないけど...)

list_ab = ["aa_a", "aa_b", "ab_a", "ab_b", "ba_a", "ba_b"]
list_prefix = ["aa", "ab"]
print(list(
    filter(lambda a: True in map(lambda b: a.startswith(b), list_prefix),
            list_ab)
))  # ['aa_a', 'aa_b', 'ab_a', 'ab_b']

これだとaE0602で怒られる(が、pylintが怒るだけなので実行はできるし結果も期待通りに得られる)

from itertools import compress
print(list(
    compress(list_ab,
                [True in [a.startswith(b) for b in list_prefix] for a in list_ab]
                )
))  # ['aa_a', 'aa_b', 'ab_a', 'ab_b']

compressを使ってリスト内包表記で書くと良い。

【python】pythonでメモリ不足になったときにすること

要約すると

  • multiprocessingをやめよう
  • GCを上手く使おう
  • numpy配列にしよう
  • 32bitにしよう
  • forで破壊的代入をしよう(遅いならcython)
  • データ圧縮しよう(実用性微妙?)
  • 物理的にメモリ増やそう

pickleの代わりにjoblibを使って永続化する

データ的に圧縮があんまり効かないので効果は薄いが、小さくはなってる
圧縮してるので書き出しまでの速度はpickeよりも当然遅い

compless=0にすると無圧縮なのでpickleで出した時とほぼ同じサイズになるが、dumpとloadにwith openとか書く必要ないのでjoblibの方が楽

import os
import pickle

import joblib
import numpy as np
import pandas as pd

dump_data = np.random.randn(10000000)

with open("dump_data.pkl", "wb") as f:
    pickle.dump(dump_data, f)

print(os.path.getsize("dump_data.pkl") / 1024 / 1024, "MB")
# 76.29409885406494 MB

joblib.dump(dump_data, "dump_data", compress=3)
print(os.path.getsize("dump_data") / 1024 / 1024, "MB")
# 73.5648946762085 MB

# joblib.load("dump_data") #読み込み

seabornの作図例あれこれ

Seabornの全メソッドを解説(その1:グラフ一覧)
Python でデータ可視化 - カッコいいヒートマップを描こう
pythonで美しいグラフ描画 -seabornを使えばデータ分析と可視化が捗る その1

pip-compileするときにegg_infoのエラーが出たら

matplotlibやseaborn関連で起きる場合が多い気がするが、egg_info云々とエラーが出てpip-compileができない場合がある。
その場合は pip-compile --rebuild するとうまくいくと思う
参考: https://github.com/jazzband/pip-tools/issues/586

別のディレクトリからimportしたい時

Python 3でのファイルのimportのしかたまとめ

__init__.pyを作って読むのがベストか

Visual Studio CodeのJupyter extensionからPlotlyを使う

めちゃめちゃ便利

HTML(html_code)init_notebook_mode()を同じCellで一気に実行すると表示されない。
なので、まずHTML(html_code)だけを実行してから、init_notebook_mode()を実行するとうまくいく(一旦表示できれば同じCellで一気に実行しても大丈夫)
JSのロードが非同期だから?

55
88
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
88