pandas - 静かなる名辞 pythonとプログラミングのこと 2020-05-07T20:42:34+09:00 hayataka2049 Hatena::Blog hatenablog://blog/10328537792367869878 DataFrameをprintしたときヘッダの日本語の列名がずれないようにする hatenablog://entry/26006613547505039 2020-04-10T06:05:32+09:00 2020-04-10T06:11:29+09:00 日本語の列名のDataFrameを扱うことは、日本人のpandasユーザにとってはありがちな展開だと思うのですが、問題はprintするとヘッダがずれてしまうことです。 >>> import pandas as pd >>> pd.DataFrame({"あああ":[1, 2], "いいい":[3, 4], "ううう":[5, 6], "えええ":[7, 8]}) あああ いいい ううう えええ 0 1 3 5 7 1 2 4 6 8 ASCIIの等幅文字を前提にしているからこんなものなのだろうと諦めていましたが、実はよしなに表示するオプションがありました。teratailでこの件の質問を見かけ… <p> 日本語の列名のDataFrameを扱うことは、日本人のpandasユーザにとってはありがちな展開だと思うのですが、問題はprintするとヘッダがずれてしまうことです。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd &gt;&gt;&gt; pd.DataFrame({<span class="synConstant">&quot;あああ&quot;</span>:[<span class="synConstant">1</span>, <span class="synConstant">2</span>], <span class="synConstant">&quot;いいい&quot;</span>:[<span class="synConstant">3</span>, <span class="synConstant">4</span>], <span class="synConstant">&quot;ううう&quot;</span>:[<span class="synConstant">5</span>, <span class="synConstant">6</span>], <span class="synConstant">&quot;えええ&quot;</span>:[<span class="synConstant">7</span>, <span class="synConstant">8</span>]}) あああ いいい ううう えええ <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">3</span> <span class="synConstant">5</span> <span class="synConstant">7</span> <span class="synConstant">1</span> <span class="synConstant">2</span> <span class="synConstant">4</span> <span class="synConstant">6</span> <span class="synConstant">8</span> </pre><p> ASCIIの等幅文字を前提にしているからこんなものなのだろうと諦めていましたが、実はよしなに表示するオプションがありました。<a href="https://teratail.com/questions/252215">teratail&#x3067;&#x3053;&#x306E;&#x4EF6;&#x306E;&#x8CEA;&#x554F;&#x3092;&#x898B;&#x304B;&#x3051;&#x3066;&#x3001;&#x3075;&#x3068;&#x4E45;&#x3005;&#x306B;&#x30EA;&#x30D5;&#x30A1;&#x30EC;&#x30F3;&#x30B9;&#x3092;&#x898B;&#x305F;&#x3089;&#x898B;&#x3064;&#x3051;&#x307E;&#x3057;&#x305F;&#x3002;</a>こういうことがあるからQAサイトは楽しいのです。</p> <blockquote> <p>Some East Asian countries use Unicode characters whose width corresponds to two Latin characters. If a DataFrame or Series contains these characters, the default output mode may not align them properly.<br /> (中略)<br /> Enabling display.unicode.east_asian_width allows pandas to check each character’s “East Asian Width” property. These characters can be aligned properly by setting this option to True. However, this will result in longer render times than the standard len function.<br /> <a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/options.html#unicode-formatting">Options and settings &mdash; pandas 1.0.3 documentation</a></p> </blockquote> <p> うまく表示してもらうためには、</p> <pre class="code lang-python" data-lang="python" data-unlink>pd.set_option(<span class="synConstant">'display.unicode.east_asian_width'</span>, <span class="synIdentifier">True</span>) </pre><p> を打ちます。東アジアで使われている文字幅で表示してあげますよというオプション名。要するに我々のためにあるようなものなので、ありがたく使わせてもらいましょう。</p><p> このようにうまくいきます。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; pd.set_option(<span class="synConstant">'display.unicode.east_asian_width'</span>, <span class="synIdentifier">True</span>) &gt;&gt;&gt; pd.DataFrame({<span class="synConstant">&quot;あああ&quot;</span>:[<span class="synConstant">1</span>, <span class="synConstant">2</span>], <span class="synConstant">&quot;いいい&quot;</span>:[<span class="synConstant">3</span>, <span class="synConstant">4</span>], <span class="synConstant">&quot;ううう&quot;</span>:[<span class="synConstant">5</span>, <span class="synConstant">6</span>], <span class="synConstant">&quot;えええ&quot;</span>:[<span class="synConstant">7</span>, <span class="synConstant">8</span>]}) あああ いいい ううう えええ <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">3</span> <span class="synConstant">5</span> <span class="synConstant">7</span> <span class="synConstant">1</span> <span class="synConstant">2</span> <span class="synConstant">4</span> <span class="synConstant">6</span> <span class="synConstant">8</span> </pre><p>(といいつつ、ブラウザ環境次第ですがこのブログ記事上ではうまく見えていない可能性が高いです。全角文字をきっちり半角文字二文字分の幅で表示してくれる環境で確認してください。)</p><p> なお、これはPythonを起動する度に毎回設定する必要があります。永続化させるために、Pythonのスタートアップ時にpandasをimportして走らせる方法が公式では推奨されています。</p><p><a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/options.html#setting-startup-options-in-python-ipython-environment">Options and settings &mdash; pandas 1.0.3 documentation</a></p><p> 素のCPythonならPYTHONSTARTUP、IPythonなら$IPYTHONDIR/profile_default/startupなどに仕掛けておけとのことですが、そのためだけにpandasをimportさせるのも微妙な感じですね。そこだけは残念なところです。</p><p><a href="https://docs.python.org/ja/3/using/cmdline.html?highlight=pythonstartup#envvar-PYTHONSTARTUP">1. &#x30B3;&#x30DE;&#x30F3;&#x30C9;&#x30E9;&#x30A4;&#x30F3;&#x3068;&#x74B0;&#x5883; &mdash; Python 3.8.2 &#x30C9;&#x30AD;&#x30E5;&#x30E1;&#x30F3;&#x30C8;</a><br /> <a href="https://maku77.github.io/python/dev/python-startup.html">PYTHONSTARTUP &#x3067; Python &#x306E;&#x30A4;&#x30F3;&#x30BF;&#x30E9;&#x30AF;&#x30C6;&#x30A3;&#x30D6;&#x30B7;&#x30A7;&#x30EB;&#x3092;&#x4FBF;&#x5229;&#x306B;&#x3059;&#x308B; | &#x307E;&#x304F;&#x307E;&#x304F;Python&#x30CE;&#x30FC;&#x30C8;</a><br /> <a href="https://qiita.com/Kodaira_/items/1dbb33f77038782a0d96">IPython&#x8D77;&#x52D5;&#x6642;&#x306B;&#x3044;&#x3064;&#x3082;&#x4F7F;&#x3046;&#x30E2;&#x30B8;&#x30E5;&#x30FC;&#x30EB;&#x3092;import&#x3059;&#x308B;&#x8A2D;&#x5B9A; - Qiita</a></p> hayataka2049 pandasで年月日時刻の列を結合して一列にする(datetime64で) hatenablog://entry/26006613474664125 2019-12-01T23:55:28+09:00 2019-12-01T23:55:28+09:00 概要 ローデータ(生データ)を取り込むと、年月日が独立して入っている感じの嫌なデータになっていることがあります。 年,月,日 1996,8,1 1998,12,2 2012,05,3 こういうのは嬉しくないので、できるだけ単一のdatetime風の型に変換しておきたいのですが、意外と難しかったりします。 文字列操作として考える 以下のように読み込みます(io.StringIOを使っていますが実際はCSVファイルだと思ってください)。 import io import pandas as pd data = """ 年,月,日 1996,8,1 1998,12,2 2012,05,3 """ d… <div class="section"> <h3>概要</h3> <p> ローデータ(生データ)を取り込むと、年月日が独立して入っている感じの嫌なデータになっていることがあります。</p> <pre class="code" data-lang="" data-unlink>年,月,日 1996,8,1 1998,12,2 2012,05,3</pre><p> こういうのは嬉しくないので、できるだけ単一のdatetime風の型に変換しておきたいのですが、意外と難しかったりします。</p> </div> <div class="section"> <h3>文字列操作として考える</h3> <p> 以下のように読み込みます(<a href="https://www.haya-programming.com/entry/2018/07/03/042203">io.StringIO&#x3092;&#x4F7F;&#x3063;&#x3066;&#x3044;&#x307E;&#x3059;&#x304C;</a>実際はCSVファイルだと思ってください)。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> io <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd data = <span class="synConstant">&quot;&quot;&quot;</span> <span class="synConstant">年,月,日</span> <span class="synConstant">1996,8,1</span> <span class="synConstant">1998,12,2</span> <span class="synConstant">2012,05,3</span> <span class="synConstant">&quot;&quot;&quot;</span> df = pd.read_csv(io.StringIO(data), dtype={k:<span class="synIdentifier">object</span> <span class="synStatement">for</span> k <span class="synStatement">in</span> <span class="synConstant">&quot;年月日&quot;</span>}) </pre><p> 型をobject型にしておくのがミソで、整数型にされると文字列操作で変換できません。読み込んでからastypeで変換してもいいですが、二度手間ですね。</p> <pre class="code lang-python" data-lang="python" data-unlink>df[<span class="synConstant">&quot;DateTime&quot;</span>] = pd.to_datetime(df[<span class="synConstant">&quot;年&quot;</span>].str.cat([df[<span class="synConstant">&quot;月&quot;</span>], df[<span class="synConstant">&quot;日&quot;</span>]], sep=<span class="synConstant">&quot; &quot;</span>)) <span class="synIdentifier">print</span>(df) <span class="synConstant">&quot;&quot;&quot; =&gt;</span> <span class="synConstant"> 年 月 日 DateTime</span> <span class="synConstant">0 1996 8 1 1996-08-01</span> <span class="synConstant">1 1998 12 2 1998-12-02</span> <span class="synConstant">2 2012 05 3 2012-05-03</span> <span class="synConstant">&quot;&quot;&quot;</span> </pre><p> これはこれでできるのですが、文字列を介すると二度手間感が否めません。</p> </div> <div class="section"> <h3>時刻もある場合</h3> <p> とにかくそれっぽいフォーマットに無理矢理仕立てれば、この方法でできます(というかできるはずです)。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> io <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd data = <span class="synConstant">&quot;&quot;&quot;</span> <span class="synConstant">年,月,日,時,分</span> <span class="synConstant">1996,8,1,12,5</span> <span class="synConstant">1998,12,2,4,12</span> <span class="synConstant">2012,05,3,23,56</span> <span class="synConstant">&quot;&quot;&quot;</span> df = pd.read_csv(io.StringIO(data), dtype={k:<span class="synIdentifier">object</span> <span class="synStatement">for</span> k <span class="synStatement">in</span> <span class="synConstant">&quot;年月日時分&quot;</span>}) df[<span class="synConstant">&quot;DateTime&quot;</span>] = pd.to_datetime(df[<span class="synConstant">&quot;年&quot;</span>].str.cat([df[<span class="synConstant">&quot;月&quot;</span>], df[<span class="synConstant">&quot;日&quot;</span>], df[<span class="synConstant">&quot;時&quot;</span>]], sep=<span class="synConstant">&quot; &quot;</span>).str.cat(df[<span class="synConstant">&quot;分&quot;</span>], sep=<span class="synConstant">&quot;:&quot;</span>)) <span class="synIdentifier">print</span>(df) <span class="synConstant">&quot;&quot;&quot; =&gt;</span> <span class="synConstant"> 年 月 日 時 分 DateTime</span> <span class="synConstant">0 1996 8 1 12 5 1996-08-01 12:05:00</span> <span class="synConstant">1 1998 12 2 4 12 1998-12-02 04:12:00</span> <span class="synConstant">2 2012 05 3 23 56 2012-05-03 23:56:00</span> <span class="synConstant">&quot;&quot;&quot;</span> </pre><p> やはりスマートではない。</p> </div> <div class="section"> <h3>内包表記でdatetimeっぽい型のリストにすればいいんだよ</h3> <p> そう、普通はそうしたいところ。</p><p> 型で迷うと思いますが、たぶんTimestampでいいと思います。</p><p><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Timestamp.html">pandas.Timestamp &mdash; pandas 0.25.3 documentation</a><br /> </p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> io <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd data = <span class="synConstant">&quot;&quot;&quot;</span> <span class="synConstant">年,月,日,時,分</span> <span class="synConstant">1996,8,1,12,5</span> <span class="synConstant">1998,12,2,4,12</span> <span class="synConstant">2012,05,3,23,56</span> <span class="synConstant">&quot;&quot;&quot;</span> df = pd.read_csv(io.StringIO(data)) df[<span class="synConstant">&quot;DateTime&quot;</span>] = [ pd.Timestamp( year=row[<span class="synConstant">&quot;年&quot;</span>], month=row[<span class="synConstant">&quot;月&quot;</span>], day=row[<span class="synConstant">&quot;日&quot;</span>], hour=row[<span class="synConstant">&quot;時&quot;</span>], minute=row[<span class="synConstant">&quot;分&quot;</span>]) <span class="synStatement">for</span> i, row <span class="synStatement">in</span> df.iterrows()] <span class="synIdentifier">print</span>(df) <span class="synConstant">&quot;&quot;&quot; =&gt;</span> <span class="synConstant"> 年 月 日 時 分 DateTime</span> <span class="synConstant">0 1996 8 1 12 5 1996-08-01 12:05:00</span> <span class="synConstant">1 1998 12 2 4 12 1998-12-02 04:12:00</span> <span class="synConstant">2 2012 5 3 23 56 2012-05-03 23:56:00</span> <span class="synConstant">&quot;&quot;&quot;</span> </pre><p> 読み込みで文字列にしないといけない、二度手間、といった微妙さがなくなりました。わーい。</p><p> これはこれで上手くいきます。が、スマートなはずなのにスマートに見えない。キーワード引数の指定が汚すぎるからですね。</p><p> ダブルアスタリスクのアンパックを使えば……とか一瞬は思いましたが、そのためには列名を変えたdfをコピーして作らないといけません。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> io <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd data = <span class="synConstant">&quot;&quot;&quot;</span> <span class="synConstant">年,月,日,時,分</span> <span class="synConstant">1996,8,1,12,5</span> <span class="synConstant">1998,12,2,4,12</span> <span class="synConstant">2012,05,3,23,56</span> <span class="synConstant">&quot;&quot;&quot;</span> df = pd.read_csv(io.StringIO(data)) df_d = df[[<span class="synConstant">&quot;年&quot;</span>, <span class="synConstant">&quot;月&quot;</span>, <span class="synConstant">&quot;日&quot;</span>, <span class="synConstant">&quot;時&quot;</span>, <span class="synConstant">&quot;分&quot;</span>]].copy() df_d.columns = [<span class="synConstant">&quot;year&quot;</span>, <span class="synConstant">&quot;month&quot;</span>, <span class="synConstant">&quot;day&quot;</span>, <span class="synConstant">&quot;hour&quot;</span>, <span class="synConstant">&quot;minute&quot;</span>] df[<span class="synConstant">&quot;DateTime&quot;</span>] = [pd.Timestamp(**row) <span class="synStatement">for</span> i, row <span class="synStatement">in</span> df_d.iterrows()] <span class="synIdentifier">print</span>(df) <span class="synConstant">&quot;&quot;&quot; =&gt;</span> <span class="synConstant"> 年 月 日 時 分 DateTime</span> <span class="synConstant">0 1996 8 1 12 5 1996-08-01 12:05:00</span> <span class="synConstant">1 1998 12 2 4 12 1998-12-02 04:12:00</span> <span class="synConstant">2 2012 5 3 23 56 2012-05-03 23:56:00</span> <span class="synConstant">&quot;&quot;&quot;</span> </pre><p> こっちの方が多少スマートかな。上の書き方でも別に困ることはないです。</p> </div> <div class="section"> <h3>まとめ</h3> <p> 普通にTimestampのiterableを突っ込めばいいだけだけど、このやり方が調べても出てこなくて、できないのかなとか思って焦りつつやってみたらできたので記事にしました。</p><p> 日付時刻の扱いは割と面倒ですが、けっきょくのところ素直に組んでいけば良いはず。</p> </div> <div class="section"> <h3>参考</h3> <p><a href="https://qiita.com/kawagucchi_suzuki/items/a1b3e1ca142a4454934c">Pandas&#x3067;&#x306E;&#x65E5;&#x4ED8;&#x30FB;&#x6642;&#x9593;&#x5468;&#x308A;&#x306E;&#x3061;&#x3087;&#x3063;&#x3068;&#x3057;&#x305F;&#x30C1;&#x30FC;&#x30C8;&#x30B7;&#x30FC;&#x30C8; - Qiita</a><br />  これと同じようなことをやっています。</p> </div> hayataka2049 【python】機械学習でpandas.get_dummiesを使ってはいけない hatenablog://entry/26006613398191700 2019-08-17T18:45:27+09:00 2019-08-31T22:13:42+09:00 「pandasのget_dummiesでダミー変数が作れるぜ」という記事がとてもたくさんあって初心者を混乱させているのですが、これは「データ分析」には使えても「機械学習」には向きません。もう少し正確に言い換えると「訓練データからモデルを作り、未知のデータの予測を行うタスク」には使い勝手が悪いものです。 <div class="section"> <h3>はじめに</h3> <p> 「pandasのget_dummiesでダミー変数が作れるぜ」という記事がとてもたくさんあって初心者を混乱させているのですが、これは「データ分析」には使えても「機械学習」には向きません。もう少し正確に言い換えると「訓練データからモデルを作り、未知のデータの予測を行うタスク」には使い勝手が悪いものです。</p><p> 機械学習に使ってはいけないというのは大げさかもしれませんが、でも間違った使い方をよく見かけますし、こう言い切った方がぶっちゃけ良いと思います。</p><p> この記事では「こういうときにはget_dummies使うんじゃねえ!」ということと、どういう問題があるのかと、代替方法について書きます。</p><p><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html">pandas.get_dummies &mdash; pandas 0.25.1 documentation</a></p><p></p> </div> <div class="section"> <h3>問題点</h3> <p> こんなデータを考えましょう。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd &gt;&gt;&gt; df = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>:[<span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;fuga&quot;</span>], <span class="synConstant">&quot;B&quot;</span>:[<span class="synConstant">&quot;a&quot;</span>, <span class="synConstant">&quot;b&quot;</span>]}) &gt;&gt;&gt; df A B <span class="synConstant">0</span> hoge a <span class="synConstant">1</span> fuga b &gt;&gt;&gt; pd.get_dummies(df) A_fuga A_hoge B_a B_b <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> </pre><p> 問題なさそうに見えますか?</p><p> でも、複数のデータに対して適用しようとするととたんに大問題が発生します。普通、kaggleのコンペとかならtrainとtestのデータはあるわけですよね。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; df_train = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>:[<span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;fuga&quot;</span>], <span class="synConstant">&quot;B&quot;</span>:[<span class="synConstant">&quot;a&quot;</span>, <span class="synConstant">&quot;b&quot;</span>]}) &gt;&gt;&gt; df_test = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>:[<span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;piyo&quot;</span>], <span class="synConstant">&quot;B&quot;</span>:[<span class="synConstant">&quot;a&quot;</span>, <span class="synConstant">&quot;c&quot;</span>]}) &gt;&gt;&gt; pd.get_dummies(df_train) A_fuga A_hoge B_a B_b <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> &gt;&gt;&gt; pd.get_dummies(df_test) A_hoge A_piyo B_a B_c <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> </pre><p> shapeは同じ。だけど、各カラムの意味するものは異なっています。一致しているのはB_aだけという惨状です。</p><p> ユニークな要素は6つあるので、下のようになればまずまずの結果と言っていいかもしれません。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># trainに対して</span> A_fuga A_hoge A_piyo B_a B_b B_c <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synComment"># testに対して</span> A_fuga A_hoge A_piyo B_a B_b B_c <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> </pre><p> 実際は学習データに含まれない値なんて落ちてくれて構わない(逆に落ちないと厄介)ので、理想的な結果はこうでしょうか。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># trainに対して</span> A_fuga A_hoge B_a B_b <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synComment"># testに対して</span> A_fuga A_hoge B_a B_b <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">0</span> </pre><p> ドキュメントを軽く読んでいろいろ試した感じ、これをget_dummiesで得るのは無理っぽいです。つかえねー。<br /> (私が見落としているだけかもしれないので、「できるよ」という人はコメントで教えて下さい。確認した上で記事に反映させていただきます。)<br /> (↑さっそくコメントを頂いて、追記させていただきました。この章の末尾を御覧ください。)</p><p> こういう問題があるので、get_dummiesはダメと言っています。</p><p> なお、先に示した6列のデータなら、pandas.concatしてから変換すれば得ることができます。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; ret = pd.get_dummies(pd.concat([df_train, df_test])) A_fuga A_hoge A_piyo B_a B_b B_c <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> &gt;&gt;&gt; ret = pd.get_dummies(pd.concat([df_train, df_test])) &gt;&gt;&gt; X_train, X_test = ret.iloc[:<span class="synConstant">2</span>], ret.iloc[<span class="synConstant">2</span>:] &gt;&gt;&gt; X_train A_fuga A_hoge A_piyo B_a B_b B_c <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> &gt;&gt;&gt; X_test A_fuga A_hoge A_piyo B_a B_b B_c <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> </pre><p> これをやっているコードも見かけたことがありますが、「予測モデル側で学習データぜんぶ持っておくの?」ということを考えると現実的なソリューションではないでしょう。おすすめしません。</p><p><b>追記</b><br />  列をpandas.Categorical型とすれば、明示的にカテゴリを指定することで変換が可能なようです。</p> <blockquote> <pre class="code lang-python" data-lang="python" data-unlink>df_train = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>: [<span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;fuga&quot;</span>], <span class="synConstant">&quot;B&quot;</span>: [<span class="synConstant">&quot;a&quot;</span>, <span class="synConstant">&quot;b&quot;</span>]}) df_test = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>: [<span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;piyo&quot;</span>], <span class="synConstant">&quot;B&quot;</span>: [<span class="synConstant">&quot;a&quot;</span>, <span class="synConstant">&quot;c&quot;</span>]}) df_test[<span class="synConstant">&quot;A&quot;</span>] = pd.Categorical(df_test[<span class="synConstant">&quot;A&quot;</span>], categories=[<span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;fuga&quot;</span>]) df_test[<span class="synConstant">&quot;B&quot;</span>] = pd.Categorical(df_test[<span class="synConstant">&quot;B&quot;</span>], categories=[<span class="synConstant">&quot;a&quot;</span>, <span class="synConstant">&quot;b&quot;</span>]) pd.get_dummies(df_test) </pre><p><a href="http://tenergima.hateblo.jp/">&#x30C6;&#x30CA;&#x30B8;&#x30DE;&#x69D8;</a>コメントより</p> </blockquote> <p> scikit-learnでやるのと比べて記述は増えますが、pandasの枠組みの中で取り扱うこと自体は可能なようです。</p><p> <a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Categorical.html">pandas.Categorical &mdash; pandas 0.25.1 documentation</a><br /> </p> </div> <div class="section"> <h3>代替する方法</h3> <p> sklearnのOneHotEncoderで変換すれば一発です。</p><p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html">sklearn.preprocessing.OneHotEncoder &mdash; scikit-learn 0.21.3 documentation</a><br /> </p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">from</span> sklearn.preprocessing <span class="synPreProc">import</span> OneHotEncoder &gt;&gt;&gt; ohe = OneHotEncoder(handle_unknown=<span class="synConstant">&quot;ignore&quot;</span>, sparse=<span class="synIdentifier">False</span>) &gt;&gt;&gt; ohe.fit(df_train) OneHotEncoder(categorical_features=<span class="synIdentifier">None</span>, categories=<span class="synIdentifier">None</span>, drop=<span class="synIdentifier">None</span>, dtype=&lt;<span class="synStatement">class</span> <span class="synConstant">'numpy.float64'</span>&gt;, handle_unknown=<span class="synConstant">'ignore'</span>, n_values=<span class="synIdentifier">None</span>, sparse=<span class="synIdentifier">False</span>) &gt;&gt;&gt; ohe.transform(df_train) array([[<span class="synConstant">0.</span>, <span class="synConstant">1.</span>, <span class="synConstant">1.</span>, <span class="synConstant">0.</span>], [<span class="synConstant">1.</span>, <span class="synConstant">0.</span>, <span class="synConstant">0.</span>, <span class="synConstant">1.</span>]]) &gt;&gt;&gt; ohe.transform(df_test) array([[<span class="synConstant">0.</span>, <span class="synConstant">1.</span>, <span class="synConstant">1.</span>, <span class="synConstant">0.</span>], [<span class="synConstant">0.</span>, <span class="synConstant">0.</span>, <span class="synConstant">0.</span>, <span class="synConstant">0.</span>]]) </pre><p> 一撃で理想的な結果を得られています。scikit-learnは偉大ですね。</p><p> pandasなんて最初から要らなかった。</p><p> これはscikit-learnのモデルなので、Pipelineなどと組み合わせて使うのにも親和性が高いです。というか、そのように使ってください(Pipelineにすることで、transformするべきところでfit_transformするといった凡ミスを防げます)。</p><p> 使い方についてはこっちの記事も参照してください。</p><p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.haya-programming.com%2Fentry%2F2018%2F12%2F02%2F042049" title="【python】sklearnでのカテゴリ変数の取り扱いまとめ LabelEncoder, OneHotEncoderなど - 静かなる名辞" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><a href="https://www.haya-programming.com/entry/2018/12/02/042049">&#x3010;python&#x3011;sklearn&#x3067;&#x306E;&#x30AB;&#x30C6;&#x30B4;&#x30EA;&#x5909;&#x6570;&#x306E;&#x53D6;&#x308A;&#x6271;&#x3044;&#x307E;&#x3068;&#x3081; LabelEncoder, OneHotEncoder&#x306A;&#x3069; - &#x9759;&#x304B;&#x306A;&#x308B;&#x540D;&#x8F9E;</a></p><p> ColumnTransformerと組み合わせると使い方の幅が広がります。カテゴリ変数だけ投げて数値変数はそのまま通すといった処理が可能になります。</p><p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.haya-programming.com%2Fentry%2F2019%2F06%2F29%2F194801" title="scikit-learnのColumnTransformerを使ってみる - 静かなる名辞" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><a href="https://www.haya-programming.com/entry/2019/06/29/194801">scikit-learn&#x306E;ColumnTransformer&#x3092;&#x4F7F;&#x3063;&#x3066;&#x307F;&#x308B; - &#x9759;&#x304B;&#x306A;&#x308B;&#x540D;&#x8F9E;</a></p><p> あとこれは完全に余談ですが、その気になればnanもsklearnの中で落とせます。前処理からすべてscikit-learnの枠組みの中で書けるので、pandasの出る幕はCSVの読み込みと探索的データ分析でやる各種プロットとか以外にはないと言っても過言ではないでしょう。</p><p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fscikit-learn.org%2Fstable%2Fmodules%2Fimpute.html" title="5.4. Imputation of missing values — scikit-learn 0.21.3 documentation" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><a href="https://scikit-learn.org/stable/modules/impute.html">5.4. Imputation of missing values &mdash; scikit-learn 0.21.3 documentation</a></p><p> ……え、結果がpandasのDataFrameになってないのがいやだって? そしたら、結果を改めてDataFrameに変換すればいいんじゃないでしょうか。こんな感じですね。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; pd.DataFrame(ohe.transform(df_test), columns=[c + <span class="synConstant">&quot;_&quot;</span> + x <span class="synStatement">for</span> lst, c <span class="synStatement">in</span> <span class="synIdentifier">zip</span>(ohe.categories_, <span class="synConstant">&quot;AB&quot;</span>) <span class="synStatement">for</span> x <span class="synStatement">in</span> lst]) A_fuga A_hoge B_a B_b <span class="synConstant">0</span> <span class="synConstant">0.0</span> <span class="synConstant">1.0</span> <span class="synConstant">1.0</span> <span class="synConstant">0.0</span> <span class="synConstant">1</span> <span class="synConstant">0.0</span> <span class="synConstant">0.0</span> <span class="synConstant">0.0</span> <span class="synConstant">0.0</span> </pre> </div> <div class="section"> <h3>まとめ</h3> <p> pandasは基本的にこういう用途には向いていないので、安易に使わないほうが良いという話です。機械学習ライブラリとして枠組みを整備してくれているscikit-learnは偉大なツールなので、積極的にこっちを活用していけばいいと思います。</p> </div> hayataka2049 pythonで相関係数を計算する方法いろいろ3種類 hatenablog://entry/17680117127218871488 2019-07-18T04:16:46+09:00 2019-08-31T22:15:03+09:00 はじめに pythonで相関係数を計算する方法はいろいろあります。確認したら、主要ライブラリだけで3つありました。 いろいろあるということは用途によって使い分けられるということなので、淡々と書いていきます。 なお、念のために断っておくと、ここで書いている「相関係数」はすべて「ピアソンの積立相関係数」です。順位相関などはまた別に調べてください(ただしpandasを使う方法だと出せます)。 目次 はじめに データの確認 numpyでやる pandasでやる scipyを使う あと思ったこととか まとめ データの確認 予め以下のようなデータを定義しておきます。 >>> import numpy as… <div class="section"> <h3 id="はじめに">はじめに</h3> <p> pythonで相関係数を計算する方法はいろいろあります。確認したら、主要ライブラリだけで3つありました。</p><p> いろいろあるということは用途によって使い分けられるということなので、淡々と書いていきます。</p><p> なお、念のために断っておくと、ここで書いている「相関係数」はすべて「ピアソンの積立相関係数」です。順位相関などはまた別に調べてください(ただしpandasを使う方法だと出せます)。</p><p> 目次</p> <ul class="table-of-contents"> <li><a href="#はじめに">はじめに</a></li> <li><a href="#データの確認">データの確認</a></li> <li><a href="#numpyでやる">numpyでやる</a></li> <li><a href="#pandasでやる">pandasでやる</a></li> <li><a href="#scipyを使う">scipyを使う</a></li> <li><a href="#あと思ったこととか">あと思ったこととか</a></li> <li><a href="#まとめ">まとめ</a></li> </ul> </div> <div class="section"> <h3 id="データの確認">データの確認</h3> <p> 予め以下のようなデータを定義しておきます。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> numpy <span class="synStatement">as</span> np &gt;&gt;&gt; np.random.seed(<span class="synConstant">0</span>) &gt;&gt;&gt; x = np.arange(<span class="synConstant">0</span>, <span class="synConstant">10</span>, <span class="synConstant">0.1</span>) &gt;&gt;&gt; y = x + np.random.normal(size=x.shape) </pre><p> 散布図にプロットして確認。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> matplotlib.pyplot <span class="synStatement">as</span> plt &gt;&gt;&gt; plt.scatter(x, y) &lt;matplotlib.collections.PathCollection <span class="synIdentifier">object</span> at <span class="synConstant">0x7f31aa415f28</span>&gt; &gt;&gt;&gt; plt.savefig(<span class="synConstant">&quot;fig.png&quot;</span>) </pre><p><figure class="figure-image figure-image-fotolife" title="fig.png"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hayataka2049/20190718/20190718035459.png" alt="fig.png" title="f:id:hayataka2049:20190718035459p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>fig.png</figcaption></figure></p><p> もう少しサンプル数が少なくても良かったような気もしますが、せっかく定義したのでこれでやります。</p> </div> <div class="section"> <h3 id="numpyでやる">numpyでやる</h3> <p> numpyの場合はnp.corrcoefで相関係数「行列」を出してくれます。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; np.corrcoef(x, y) array([[<span class="synConstant">1.</span> , <span class="synConstant">0.94129622</span>], [<span class="synConstant">0.94129622</span>, <span class="synConstant">1.</span> ]]) </pre><p> 0.9以上なので強い相関があるみたいです。「行列」が出てくるので、単に相関係数がほしいときは適当に取り出します。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; np.corrcoef(x, y)[<span class="synConstant">0</span>, <span class="synConstant">1</span>] <span class="synConstant">0.9412962237004372</span> </pre><p> あまりスマートではないので、本当に相関係数「行列」がほしいときに使います。</p><p><a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.corrcoef.html">numpy.corrcoef &mdash; NumPy v1.17 Manual</a></p><p></p> </div> <div class="section"> <h3 id="pandasでやる">pandasでやる</h3> <p> pandasでもnumpyと同じことができるようです。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd &gt;&gt;&gt; df = pd.DataFrame({<span class="synConstant">&quot;x&quot;</span>:x, <span class="synConstant">&quot;y&quot;</span>:y}) &gt;&gt;&gt; df.corr() x y x <span class="synConstant">1.000000</span> <span class="synConstant">0.941296</span> y <span class="synConstant">0.941296</span> <span class="synConstant">1.000000</span> </pre><p> 行と列に名前がついて使いやすくなったと思います。また、ピアソン以外の相関係数も、kendall, spearmanをmethod引数に渡すことができ、なんならcallableで任意の関数で計算することもできるといった使いやすさがあります。多機能ですね。</p><p><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.corr.html">pandas.DataFrame.corr &mdash; pandas 0.25.1 documentation</a></p><br /> <p> あと、相関係数「行列」がほしいときはpandasを経由した方が便利でしょうか。seabornに投げて可視化するときに、行・列の名前を考慮してくれるので、便利そうです。</p><p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fnote.nkmk.me%2Fpython-pandas-corr%2F" title="pandas.DataFrameの各列間の相関係数を算出、ヒートマップで可視化 | note.nkmk.me" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><a href="https://note.nkmk.me/python-pandas-corr/">pandas.DataFrame&#x306E;&#x5404;&#x5217;&#x9593;&#x306E;&#x76F8;&#x95A2;&#x4FC2;&#x6570;&#x3092;&#x7B97;&#x51FA;&#x3001;&#x30D2;&#x30FC;&#x30C8;&#x30DE;&#x30C3;&#x30D7;&#x3067;&#x53EF;&#x8996;&#x5316; | note.nkmk.me</a></p><p></p> </div> <div class="section"> <h3 id="scipyを使う">scipyを使う</h3> <p> 漢は黙ってscipy、という価値観が私にはあります。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">from</span> scipy <span class="synPreProc">import</span> stats &gt;&gt;&gt; stats.pearsonr(x, y) (<span class="synConstant">0.941296223700437</span>, <span class="synConstant">5.153124094421605e-48</span>) </pre><p> 勝手に両側検定をやってp値を出してくれています(結果のtupleの0から数えて1つめ)。</p><p><a href="https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html">scipy.stats.pearsonr &mdash; SciPy v1.3.0 Reference Guide</a></p><p> 検定やってくれるのはいいですね。普通は別途やる必要があると思います。</p> </div> <div class="section"> <h3 id="あと思ったこととか">あと思ったこととか</h3> <ul> <li>なんで標準のstatisticsで用意されてないの</li> <li>statsmodelsは高度な機能はいろいろ提供しているくせに、ただの相関係数の出し方がいくらググっても出てこないのはなんで。リファレンスすごく読みづらいし。あるかもしれないけど諦めた</li> </ul> </div> <div class="section"> <h3 id="まとめ">まとめ</h3> <p> まあ、3つあればいいか……行列がほしいときは楽そうなのはpandas、単に数字がほしければscipyという使い分けになりそうですね。</p> </div> hayataka2049 【python】pandasのto_sqlを試してみる hatenablog://entry/17680117127104484144 2019-05-03T04:33:34+09:00 2019-06-28T00:25:27+09:00 はじめに 気軽にDataFrameをデータベーステーブルに変換できそうなto_sqlなるものがあるので、試してみます。pandas.DataFrame.to_sql — pandas 0.23.4 documentation sqliteを使いたかった ドキュメントではSQLAlchemyを使ってSQLiteを叩いているようですが、SQLAlchemy*1は素人なので、ここでのファイルの指定方法がいまいち謎です。 とりあえず、データベースエンジン — SQLAlchemy 0.6.5 ドキュメント (和訳) をざっと眺めて適当にやったら、エラーが出ました。 sqlalchemy.exc.Arg… <div class="section"> <h3>はじめに</h3> <p> 気軽にDataFrameをデータベーステーブルに変換できそうなto_sqlなるものがあるので、試してみます。</p><p><a href="https://pandas.pydata.org/pandas-docs/version/0.23.4/generated/pandas.DataFrame.to_sql.html">pandas.DataFrame.to_sql &mdash; pandas 0.23.4 documentation</a></p><p></p> </div> <div class="section"> <h3>sqliteを使いたかった</h3> <p> ドキュメントではSQLAlchemyを使ってSQLiteを叩いているようですが、SQLAlchemy<a href="#f-cb1a2bae" name="fn-cb1a2bae" title="ところで、こういうタイピングに苦痛を伴う命名はやめてほしい">*1</a>は素人なので、ここでのファイルの指定方法がいまいち謎です。</p><p> とりあえず、</p><p><a href="http://omake.accense.com/static/doc-ja/sqlalchemy/dbengine.html">&#x30C7;&#x30FC;&#x30BF;&#x30D9;&#x30FC;&#x30B9;&#x30A8;&#x30F3;&#x30B8;&#x30F3; &mdash; SQLAlchemy 0.6.5 &#x30C9;&#x30AD;&#x30E5;&#x30E1;&#x30F3;&#x30C8; (&#x548C;&#x8A33;)</a></p><p> をざっと眺めて適当にやったら、エラーが出ました。</p> <pre class="code" data-lang="" data-unlink>sqlalchemy.exc.ArgumentError: Invalid SQLite URL: sqlite://test.db Valid SQLite URL forms are: sqlite:///:memory: (or, sqlite://) sqlite:///relative/path/to/file.db sqlite:////absolute/path/to/file.db</pre><p> あ、なるほど、相対パスならスラッシュ3つ、絶対パスならスラッシュ4つにするんですね。すごくどうでも良いところでハマりました。</p> </div> <div class="section"> <h3>実行して確認してみる</h3> <p> 何はともあれ、こんなコードを実行します。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd <span class="synPreProc">from</span> sqlalchemy <span class="synPreProc">import</span> create_engine df = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>:[<span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;fuga&quot;</span>], <span class="synConstant">&quot;B&quot;</span>:[<span class="synConstant">1</span>, <span class="synConstant">2</span>], <span class="synConstant">&quot;C&quot;</span>:[<span class="synConstant">1.0</span>, <span class="synConstant">2.0</span>]}) engine = create_engine(<span class="synConstant">'sqlite:///test.db'</span>, echo=<span class="synIdentifier">False</span>) df.to_sql(<span class="synConstant">&quot;df1&quot;</span>, engine) </pre><p> lsしてtest.dbが生成されたことを確認したら、コンソールからsqliteでつなぎます。</p> <pre class="code" data-lang="" data-unlink>$ sqlite3 test.db sqlite&gt; .tables df1 sqlite&gt; .schema df1 CREATE TABLE df1 ( &#34;index&#34; BIGINT, &#34;A&#34; TEXT, &#34;B&#34; BIGINT, &#34;C&#34; FLOAT ); CREATE INDEX ix_df1_index ON df1 (&#34;index&#34;); sqlite&gt; select A, B, C from df1; hoge|1|1.0 fuga|2|2.0</pre><p> まずはできてるっぽくて安心。型はよくわからないけど、こんなものだと思います。</p> </div> <div class="section"> <h3>複数回実行</h3> <p> 問題になりそうなのは複数回呼んだときにどうなるかです。DataFrameを更新してテーブルにも反映する・・・といった処理を想定しています。</p><p> デフォルトの挙動は「エラーになる」です。</p> <pre class="code" data-lang="" data-unlink>ValueError: Table &#39;df1&#39; already exists.</pre><p> ただしまったく使えないという訳ではなく、ドキュメントに書いてあることですが、</p> <blockquote> <p>if_exists : {‘fail’, ‘replace’, ‘append’}, default ‘fail’</p> </blockquote> <p> というパラメータがあって、これで調整できます。</p><p> dfの定義を書き換えて、if_exists="replace"にして実行してみます。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd <span class="synPreProc">from</span> sqlalchemy <span class="synPreProc">import</span> create_engine df = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>:[<span class="synConstant">&quot;aa&quot;</span>, <span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;fuga&quot;</span>], <span class="synConstant">&quot;B&quot;</span>:[-<span class="synConstant">100</span>, <span class="synConstant">1</span>, <span class="synConstant">2</span>], <span class="synConstant">&quot;C&quot;</span>:[-<span class="synConstant">100.0</span>, <span class="synConstant">1.0</span>, <span class="synConstant">2.0</span>]}) engine = create_engine(<span class="synConstant">'sqlite:///test.db'</span>, echo=<span class="synIdentifier">False</span>) df.to_sql(<span class="synConstant">&quot;df1&quot;</span>, engine, if_exists=<span class="synConstant">&quot;replace&quot;</span>) </pre><p> 実行してから中身を見ます。</p> <pre class="code" data-lang="" data-unlink>$ sqlite3 test.db sqlite&gt; select A, B, C from df1; aa|-100|-100.0 hoge|1|1.0 fuga|2|2.0</pre><p> テーブルの形が変わっても同様のことができます。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd <span class="synPreProc">from</span> sqlalchemy <span class="synPreProc">import</span> create_engine df = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>:[<span class="synConstant">&quot;aa&quot;</span>, <span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;fuga&quot;</span>], <span class="synConstant">&quot;B&quot;</span>:[-<span class="synConstant">100</span>, <span class="synConstant">1</span>, <span class="synConstant">2</span>], <span class="synConstant">&quot;C&quot;</span>:[-<span class="synConstant">100.0</span>, <span class="synConstant">1.0</span>, <span class="synConstant">2.0</span>], <span class="synConstant">&quot;D&quot;</span>:[<span class="synConstant">1</span>, <span class="synConstant">2</span>, <span class="synConstant">3</span>]}) engine = create_engine(<span class="synConstant">'sqlite:///test.db'</span>, echo=<span class="synIdentifier">False</span>) df.to_sql(<span class="synConstant">&quot;df1&quot;</span>, engine, if_exists=<span class="synConstant">&quot;replace&quot;</span>) </pre><pre class="code" data-lang="" data-unlink>sqlite&gt; select A, B, C, D from df1; aa|-100|-100.0|1 hoge|1|1.0|2 fuga|2|2.0|3</pre><p> 一回消して作り直しているのと同じようなものと考えるべき・・・でしょうか。</p><p> 続けてappendを試します。</p> <blockquote> <p>append: Insert new values to the existing table.</p> </blockquote> <p> いまいちよくわからない説明なので、念の為に新しいテーブルを作って試します。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd <span class="synPreProc">from</span> sqlalchemy <span class="synPreProc">import</span> create_engine df = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>:[<span class="synConstant">&quot;aa&quot;</span>, <span class="synConstant">&quot;hoge&quot;</span>, <span class="synConstant">&quot;fuga&quot;</span>], <span class="synConstant">&quot;B&quot;</span>:[-<span class="synConstant">100</span>, <span class="synConstant">1</span>, <span class="synConstant">2</span>], <span class="synConstant">&quot;C&quot;</span>:[-<span class="synConstant">100.0</span>, <span class="synConstant">1.0</span>, <span class="synConstant">2.0</span>], <span class="synConstant">&quot;D&quot;</span>:[<span class="synConstant">1</span>, <span class="synConstant">2</span>, <span class="synConstant">3</span>]}) engine = create_engine(<span class="synConstant">'sqlite:///test.db'</span>, echo=<span class="synIdentifier">False</span>) df.to_sql(<span class="synConstant">&quot;df1&quot;</span>, engine, if_exists=<span class="synConstant">&quot;append&quot;</span>) </pre><pre class="code" data-lang="" data-unlink>sqlite&gt; select * from df2; 0|aa|-100 1|hoge|1</pre><p> 一回目は普通。</p><p> もう一回実行すると、下みたいになります。</p> <pre class="code" data-lang="" data-unlink>sqlite&gt; select * from df2; 0|aa|-100 1|hoge|1 0|aa|-100 1|hoge|1</pre><p> なんとなく納得しました。</p><p> 列を追加すると、どうなるんでしょうね。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd <span class="synPreProc">from</span> sqlalchemy <span class="synPreProc">import</span> create_engine df = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>:[<span class="synConstant">&quot;aa&quot;</span>, <span class="synConstant">&quot;hoge&quot;</span>], <span class="synConstant">&quot;B&quot;</span>:[-<span class="synConstant">100</span>, <span class="synConstant">1</span>], <span class="synConstant">&quot;C&quot;</span>:[<span class="synConstant">0.1</span>, <span class="synConstant">0.2</span>]}) engine = create_engine(<span class="synConstant">'sqlite:///test.db'</span>, echo=<span class="synIdentifier">False</span>) df.to_sql(<span class="synConstant">&quot;df2&quot;</span>, engine, if_exists=<span class="synConstant">&quot;append&quot;</span>) </pre><p> なんとなく予想していたことですが、エラーを吐かれました。</p> <pre class="code lang-python" data-lang="python" data-unlink>sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) table df2 has no column named C [SQL: INSERT INTO df2 (<span class="synConstant">&quot;index&quot;</span>, <span class="synConstant">&quot;A&quot;</span>, <span class="synConstant">&quot;B&quot;</span>, <span class="synConstant">&quot;C&quot;</span>) VALUES (?, ?, ?, ?)] [parameters: ((<span class="synConstant">0</span>, <span class="synConstant">'aa'</span>, -<span class="synConstant">100</span>, <span class="synConstant">0.1</span>), (<span class="synConstant">1</span>, <span class="synConstant">'hoge'</span>, <span class="synConstant">1</span>, <span class="synConstant">0.2</span>))] (Background on this error at: http://sqlalche.me/e/e3q8) </pre><p> 便利に変更部分だけ反映してくれたりはしないので、使いみちは限られると言えます。それがしたければif_exists="replace"の方が良いのですが、頻繁にやると遅くなるのでなにか考えた方が良いでしょう。</p> </div> <div class="section"> <h3>まとめ</h3> <p> ちょっと微妙・・・</p><p> 使い方次第でしょうね。pandasデータフレームを何も考えずにデータベースに突っ込めるので、そういうことをしたいときに重宝するでしょう。だけど、積極的にデータベースと連携させるために使うかというと、それは違う気がします。</p> </div><div class="footnote"> <p class="footnote"><a href="#fn-cb1a2bae" name="f-cb1a2bae" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">ところで、こういうタイピングに苦痛を伴う命名はやめてほしい</span></p> </div> hayataka2049 【python】sklearn 0.20でclassification_reportの仕様が変わっていた hatenablog://entry/17680117126995277463 2019-03-18T05:20:35+09:00 2019-09-03T22:57:56+09:00 はじめに 遅まきながら、sklearn 0.20でclassification_reportの仕様が変わったことに気づきました。 基本的な使い方は変わりませんが、それなりに大きな変化になります。 変更点 まず0.19の引数と出力のフォーマット。 sklearn.metrics.classification_report(y_true, y_pred, labels=None, target_names=None, sample_weight=None, digits=2) >>> print(classification_report(y_true, y_pred, target_names=… <div class="section"> <h3>はじめに</h3> <p> 遅まきながら、sklearn 0.20でclassification_reportの仕様が変わったことに気づきました。</p><p> 基本的な使い方は変わりませんが、それなりに大きな変化になります。</p> </div> <div class="section"> <h3>変更点</h3> <p> まず0.19の引数と出力のフォーマット。</p> <blockquote> <pre class="code lang-python" data-lang="python" data-unlink>sklearn.metrics.classification_report(y_true, y_pred, labels=<span class="synIdentifier">None</span>, target_names=<span class="synIdentifier">None</span>, sample_weight=<span class="synIdentifier">None</span>, digits=<span class="synConstant">2</span>) </pre><pre class="code" data-lang="" data-unlink>&gt;&gt;&gt; print(classification_report(y_true, y_pred, target_names=target_names)) precision recall f1-score support class 0 0.50 1.00 0.67 1 class 1 0.00 0.00 0.00 1 class 2 1.00 0.67 0.80 3 avg / total 0.70 0.60 0.61 5</pre><p><a href="https://scikit-learn.org/0.19/modules/generated/sklearn.metrics.classification_report.html">sklearn.metrics.classification_report &mdash; scikit-learn 0.19.2 documentation</a></p> </blockquote> <p> 個人的に使い慣れていたのはこちらです。</p><p> 次に0.20の引数と出力のフォーマット。</p> <blockquote> <pre class="code lang-python" data-lang="python" data-unlink>sklearn.metrics.classification_report(y_true, y_pred, labels=<span class="synIdentifier">None</span>, target_names=<span class="synIdentifier">None</span>, sample_weight=<span class="synIdentifier">None</span>, digits=<span class="synConstant">2</span>, output_dict=<span class="synIdentifier">False</span>) </pre><pre class="code" data-lang="" data-unlink>&gt;&gt;&gt; print(classification_report(y_true, y_pred, target_names=target_names)) precision recall f1-score support class 0 0.50 1.00 0.67 1 class 1 0.00 0.00 0.00 1 class 2 1.00 0.67 0.80 3 micro avg 0.60 0.60 0.60 5 macro avg 0.50 0.56 0.49 5 weighted avg 0.70 0.60 0.61 5</pre><p><a href="https://scikit-learn.org/0.20/modules/generated/sklearn.metrics.classification_report.html">sklearn.metrics.classification_report &mdash; scikit-learn 0.20.4 documentation</a></p> </blockquote> <p> 変わっていますね。まず、output_dictという引数が追加されています。使い方は容易に想像がつき、ドキュメントにも説明がある通りですが辞書を返してくれるようになります。</p><p> また、全体の結果のとりまとめのところでマイクロ平均、マクロ平均、重み付き平均を返してくれるようになりました。これらの意味については以前記事にしたので、そちらを見てください。</p><p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.haya-programming.com%2Fentry%2F2018%2F03%2F14%2F112454" title="【python】分類タスクの評価指標の解説とsklearnでの計算方法 - 静かなる名辞" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><a href="https://www.haya-programming.com/entry/2018/03/14/112454">&#x3010;python&#x3011;&#x5206;&#x985E;&#x30BF;&#x30B9;&#x30AF;&#x306E;&#x8A55;&#x4FA1;&#x6307;&#x6A19;&#x306E;&#x89E3;&#x8AAC;&#x3068;sklearn&#x3067;&#x306E;&#x8A08;&#x7B97;&#x65B9;&#x6CD5; - &#x9759;&#x304B;&#x306A;&#x308B;&#x540D;&#x8F9E;</a><br /> </p> </div> <div class="section"> <h3>output_dictを試す</h3> <p> 大きな変更点はここなので、試してみましょう。ドキュメントと同様の例で打ち込んでいます。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">from</span> sklearn.metrics <span class="synPreProc">import</span> classification_report &gt;&gt;&gt; d = classification_report([<span class="synConstant">0</span>,<span class="synConstant">1</span>,<span class="synConstant">2</span>,<span class="synConstant">2</span>,<span class="synConstant">2</span>], [<span class="synConstant">0</span>,<span class="synConstant">0</span>,<span class="synConstant">2</span>,<span class="synConstant">2</span>,<span class="synConstant">1</span>], ... target_names = [<span class="synConstant">'class 0'</span>, <span class="synConstant">'class 1'</span>, <span class="synConstant">'class 2'</span>], ... output_dict=<span class="synIdentifier">True</span>) &gt;&gt;&gt; &gt;&gt;&gt; <span class="synPreProc">from</span> pprint <span class="synPreProc">import</span> pprint &gt;&gt;&gt; pprint(d) {<span class="synConstant">'class 0'</span>: {<span class="synConstant">'f1-score'</span>: <span class="synConstant">0.6666666666666666</span>, <span class="synConstant">'precision'</span>: <span class="synConstant">0.5</span>, <span class="synConstant">'recall'</span>: <span class="synConstant">1.0</span>, <span class="synConstant">'support'</span>: <span class="synConstant">1</span>}, <span class="synConstant">'class 1'</span>: {<span class="synConstant">'f1-score'</span>: <span class="synConstant">0.0</span>, <span class="synConstant">'precision'</span>: <span class="synConstant">0.0</span>, <span class="synConstant">'recall'</span>: <span class="synConstant">0.0</span>, <span class="synConstant">'support'</span>: <span class="synConstant">1</span>}, <span class="synConstant">'class 2'</span>: {<span class="synConstant">'f1-score'</span>: <span class="synConstant">0.8</span>, <span class="synConstant">'precision'</span>: <span class="synConstant">1.0</span>, <span class="synConstant">'recall'</span>: <span class="synConstant">0.6666666666666666</span>, <span class="synConstant">'support'</span>: <span class="synConstant">3</span>}, <span class="synConstant">'macro avg'</span>: {<span class="synConstant">'f1-score'</span>: <span class="synConstant">0.48888888888888893</span>, <span class="synConstant">'precision'</span>: <span class="synConstant">0.5</span>, <span class="synConstant">'recall'</span>: <span class="synConstant">0.5555555555555555</span>, <span class="synConstant">'support'</span>: <span class="synConstant">5</span>}, <span class="synConstant">'micro avg'</span>: {<span class="synConstant">'f1-score'</span>: <span class="synConstant">0.6</span>, <span class="synConstant">'precision'</span>: <span class="synConstant">0.6</span>, <span class="synConstant">'recall'</span>: <span class="synConstant">0.6</span>, <span class="synConstant">'support'</span>: <span class="synConstant">5</span>}, <span class="synConstant">'weighted avg'</span>: {<span class="synConstant">'f1-score'</span>: <span class="synConstant">0.6133333333333334</span>, <span class="synConstant">'precision'</span>: <span class="synConstant">0.7</span>, <span class="synConstant">'recall'</span>: <span class="synConstant">0.6</span>, <span class="synConstant">'support'</span>: <span class="synConstant">5</span>}} </pre><p> これはpandasデータフレームに変換できます。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd &gt;&gt;&gt; df = pd.DataFrame(d) &gt;&gt;&gt; df <span class="synStatement">class</span> <span class="synConstant">0</span> <span class="synStatement">class</span> <span class="synConstant">1</span> <span class="synStatement">class</span> <span class="synConstant">2</span> macro avg micro avg weighted avg f1-score <span class="synConstant">0.666667</span> <span class="synConstant">0.0</span> <span class="synConstant">0.800000</span> <span class="synConstant">0.488889</span> <span class="synConstant">0.6</span> <span class="synConstant">0.613333</span> precision <span class="synConstant">0.500000</span> <span class="synConstant">0.0</span> <span class="synConstant">1.000000</span> <span class="synConstant">0.500000</span> <span class="synConstant">0.6</span> <span class="synConstant">0.700000</span> recall <span class="synConstant">1.000000</span> <span class="synConstant">0.0</span> <span class="synConstant">0.666667</span> <span class="synConstant">0.555556</span> <span class="synConstant">0.6</span> <span class="synConstant">0.600000</span> support <span class="synConstant">1.000000</span> <span class="synConstant">1.0</span> <span class="synConstant">3.000000</span> <span class="synConstant">5.000000</span> <span class="synConstant">5.0</span> <span class="synConstant">5.000000</span> </pre><p> なのでデータフレームを介して記録しておきパラメータチューニングに使うとか、TeXの表やビジュアル的なグラフなど任意のフォーマットに吐き出すといった処理が行いやすくなっています。</p> </div> <div class="section"> <h3>まとめ</h3> <p> 気づくのが遅れましたが、健全な方向に改良されたと思います。使いやすくなった反面、これで済むようになると他のsklearn.metricsの関数を叩かなくなるので、使い方を忘れるかも・・・という懸念があります(笑)。</p> </div> hayataka2049 numpyやpandasでThe truth value of ... is ambiguous.のようなエラーが出たときの対処 hatenablog://entry/17680117126993904669 2019-03-15T23:52:59+09:00 2019-09-04T02:47:09+09:00 numpyやpandasでThe truth value of ... is ambiguous.のようなエラーが出たときの対処 条件式を使って生成したようなboolのnumpy配列を使っていると、次のようなエラーが出ることがあります。また、pandasのSeriesやDataFrameでも同様のエラーが発生する場合があります。 <div class="section"> <h3 id="概要">概要</h3> <p> 条件式を使って生成したようなboolのnumpy配列を使っていると、次のようなエラーが出ることがあります。</p> <pre class="code" data-lang="" data-unlink>ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()</pre><p> また、pandasのSeriesやDataFrameでも同様のエラーが発生する場合があります。</p> <pre class="code" data-lang="" data-unlink>ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().</pre><pre class="code" data-lang="" data-unlink>ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().</pre><p> この記事では、こういったエラーの原因と対処法について説明します。</p><p> 目次</p> <ul class="table-of-contents"> <li><a href="#概要">概要</a></li> <li><a href="#原因">原因</a></li> <li><a href="#対処">対処</a><ul> <li><a href="#if文の条件式にそのまま書いた">if文の条件式にそのまま書いた</a></li> <li><a href="#andやorを使った">andやorを使った</a></li> <li><a href="#複数の条件式の組み合わせで発生した">複数の条件式の組み合わせで発生した</a></li> </ul> </li> <li><a href="#まとめ">まとめ</a></li> <li><a href="#関連記事">関連記事</a></li> </ul> </div> <div class="section"> <h3 id="原因">原因</h3> <p> numpyやpandasのような複数のboolを格納できる配列・コレクションなどは、そのまま全体をbool値に変換できないことになっています。</p><p> なぜか? というと、そういったケースではコレクション全体の真理値は曖昧(ambiguous)だからです。個別の要素の値は間違いなくTrue or Falseなのですが、全体としては値が定まらないということです。</p><p> ValueErrorのメッセージでは以下のような変換が提案されています。</p> <ul> <li>a.any()かa.all()を使う</li> </ul><p> anyは要素すべてのOR、allは要素すべてのANDです。このような方法で変換するのが適切であれば、そうしてくれということです。</p> <ul> <li>a.empty(pandasのオブジェクトのみ)</li> </ul><p> 空であるかどうか。</p> <ul> <li>a.bool()(pandasのオブジェクトのみ)</li> </ul><p> ブール型の単一の要素を持つ場合、その真理値が返ります。それ以外のケースではValueErrorになるようです。</p> <ul> <li>a.item()(pandasの)</li> </ul><p> 要素数1のSeriesに対してその唯一の要素を返します。</p><p> なんとなく雰囲気がつかめてきましたね。何らかの方法で1つにまとめるなり、1つだけ取り出すなりしてくれと言っている訳です。でもまあ、この通りにすればよいかというと必ずしもそうではなく、ケースバイケースで対処する必要があります。</p><p> 余談ですが、このような挙動をするのは私が確認した範囲ではnumpyやpandasのコレクション型のみで、組み込みのlist型などではこの挙動にはなりません。どうなるかというと、皆さんよくご存知の標準的なpythonと同等の真理値判定が行われます。空リストならFalse、それ以外はTrueとかですね。</p><p><a href="https://docs.python.org/ja/3.6/library/stdtypes.html#truth-value-testing">4. &#x7D44;&#x307F;&#x8FBC;&#x307F;&#x578B; &mdash; Python 3.6.9 &#x30C9;&#x30AD;&#x30E5;&#x30E1;&#x30F3;&#x30C8;</a></p><p> numpyやpandasの実装は、大雑把に言えば__bool__が例外を送出するようにしてあるというだけのものです。たとえばpandasはこんな感じ↓です。</p><p><a href="https://github.com/pandas-dev/pandas/blob/master/pandas/core/generic.py#L1498">https://github.com/pandas-dev/pandas/blob/master/pandas/core/generic.py#L1498</a></p><p> どうしてわざわざこんなことをしているのか? というと、素のpythonと同等の判定だと(たとえば空だとFalseとか)中身のデータに対する真理値だと思いこんで処理する人が出てきたときにバグが発生するので、配慮して__bool__を潰してあるのだと思われます。</p><p> 要するに、こんな親切なメッセージまで出してくれるのは「優しさ」なので、「なんだこの腹立つエラーは」とか思ってはいけません。</p><p><span style="font-size: 80%">スポンサーリンク</span><br /> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script></p> <p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-6261827798827777" data-ad-slot="1744230936" data-ad-format="auto" data-full-width-responsive="true"></ins><br /> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script></p><p></p> </div> <div class="section"> <h3 id="対処">対処</h3> <p> 対処法ははっきり言ってケースバイケースです。このエラーはいろいろな原因で発生するので、状況にあった対処をする必要があります。</p><p> よくある(であろう)ケースを幾つか紹介してみます。</p> <div class="section"> <h4 id="if文の条件式にそのまま書いた">if文の条件式にそのまま書いた</h4> <p> if文は内部で条件式のbool値への変換を行います。ということは、このエラーが発生する可能性があります。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synStatement">if</span> numpyやpandasの配列・DataFrame、Seriesなど: .... </pre><p> これに関しては、はっきり言ってこういうことをやろうとするのが悪いです。何かしら考えが間違っていると思います。要素を一つ一つループで取り出すべきかもしれませんし、indexingで処理するべき状況の可能性もあります。あるいはそもそも期待と違うものが変数に代入されている可能性もあります。コードを全般的にデバッグしてください。</p> </div> <div class="section"> <h4 id="andやorを使った">andやorを使った</h4> <p> andやorなどの演算子は「pythonのbool」に対して働くので、numpy配列、pandasのSeriesやDataFrameに対して使うのは基本的に不適当です。これらは内部の判定時にboolへの変換を行うので、この記事で取り上げているエラーを発生させる要因になります。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(np.array([<span class="synIdentifier">True</span>, <span class="synIdentifier">False</span>]) <span class="synStatement">and</span> np.array([<span class="synIdentifier">True</span>, <span class="synIdentifier">True</span>])) <span class="synComment"># =&gt; ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()</span> </pre><p> この場合、期待しているものは&演算子と|演算子で得られるかと思われます。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(np.array([<span class="synIdentifier">True</span>, <span class="synIdentifier">False</span>]) &amp; np.array([<span class="synIdentifier">True</span>, <span class="synIdentifier">True</span>])) <span class="synComment"># =&gt; [ True False]</span> </pre><p> 他にも~や^も使えます。それぞれ論理否定(NOT)と排他的論理和(XOR)です。</p><p> なお少し補足しておくと、&, |などは本来はスカラーのビットOR, ビットAND演算子として用いるために用意されていますが、numpy, pandasなどはこの演算子が使われたときに呼ばれるメソッドを独自に定義することで、boolean arrayに対する演算子として活用しています。面白い工夫だと思うのですが、そのせいで次の節で触れる問題も手てきます。</p> </div> <div class="section"> <h4 id="複数の条件式の組み合わせで発生した">複数の条件式の組み合わせで発生した</h4> <p> このケースは割と上級者の人でも、ハマるときはハマります。</p><p> 上述の通り、配列同士の論理演算は&や|などでできるのですが、これは==のような比較演算子より優先順位が強い演算子になります。まあ、本来はビット演算用の演算子なのを流用しているので仕方ないのですが、結果的に評価の順序が狂ってエラーになるケースがあります。</p><p><a href="https://docs.python.org/ja/3/reference/expressions.html#operator-precedence">6. &#x5F0F; (expression) &mdash; Python 3.7.4 &#x30C9;&#x30AD;&#x30E5;&#x30E1;&#x30F3;&#x30C8;</a><br /> </p> <pre class="code lang-python" data-lang="python" data-unlink>a = np.array([<span class="synConstant">0</span>,<span class="synConstant">1</span>,<span class="synConstant">2</span>]) b = np.array([<span class="synConstant">3</span>,<span class="synConstant">4</span>,<span class="synConstant">5</span>]) <span class="synIdentifier">print</span>(a == <span class="synConstant">1</span> | b == <span class="synConstant">3</span>) <span class="synComment"># =&gt; ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()</span> </pre><p> これはこう書いたのと同じです。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synIdentifier">print</span>(a == (<span class="synConstant">1</span> | b) <span class="synStatement">and</span> (<span class="synConstant">1</span> | b) == <span class="synConstant">3</span>) </pre><p> pythonの比較演算子の仕様がちょっと特殊で、連結するとandで連結したのと同じになることに留意。</p> <blockquote> <p> x < y <= z は x < y and y <= z と等価になります<br /> <a href="https://docs.python.org/ja/3/reference/expressions.html#comparisons">6. &#x5F0F; (expression) &mdash; Python 3.7.4 &#x30C9;&#x30AD;&#x30E5;&#x30E1;&#x30F3;&#x30C8;</a></p> </blockquote> <p> 幸い、かっこを付けることで、比較的容易に優先順序(評価の順番)を制御できます。</p> <pre class="code lang-python" data-lang="python" data-unlink>a = np.array([<span class="synConstant">0</span>,<span class="synConstant">1</span>,<span class="synConstant">2</span>]) b = np.array([<span class="synConstant">3</span>,<span class="synConstant">4</span>,<span class="synConstant">5</span>]) <span class="synIdentifier">print</span>((a == <span class="synConstant">1</span>) | (b == <span class="synConstant">3</span>)) <span class="synComment"># =&gt; [ True True False]</span> </pre><p> しかしまあ、ちょっと困った話です。けっきょくpythonの世界であれこれ処理しようとするとこういう細かい齟齬が出てくるので、pandasにqueryメソッドがあったりするのもむべなるかなという感があります。かといってqueryの書き方を覚えるのも面倒くさいんですが。</p> </div> </div> <div class="section"> <h3 id="まとめ">まとめ</h3> <p> 割とよく見かけるエラーですが、基本的に何かがおかしくなってしまったときに出るもので、ケースバイケースで対応することになるからかあまり掘り下げた解説がなかったので、書いてみました。この記事でどこまで深く掘り下げられているかというと少し微妙な感がありますが・・・</p><p> とにかく「複数の値が入っているから真理値が一意に決められない(ことになっている)」というのがミソなので、それだけは覚えておきましょう。</p> </div> <div class="section"> <h3 id="関連記事">関連記事</h3> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.haya-programming.com%2Fentry%2F2018%2F05%2F29%2F040327" title="【python】その矛盾した__eq__は・・・ - 静かなる名辞" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><a href="https://www.haya-programming.com/entry/2018/05/29/040327">&#x3010;python&#x3011;&#x305D;&#x306E;&#x77DB;&#x76FE;&#x3057;&#x305F;__eq__&#x306F;&#x30FB;&#x30FB;&#x30FB; - &#x9759;&#x304B;&#x306A;&#x308B;&#x540D;&#x8F9E;</a><br />  Pythonの比較演算子==の挙動についてもう少し掘り下げた記事です。</p> </div> hayataka2049 【python】pandasのgroupbyで結果をlistにする hatenablog://entry/10257846132621106421 2018-09-05T17:24:03+09:00 2018-11-28T18:57:56+09:00 pandasのgroupbyを使って、平均や標準偏差を計算する方法は検索するとすぐ出てきます。 ただ、「そういうの良いから、項目ごとに使いやすいイテレータにしてまとめてくれよ!」と思うときがありますよね。 >>> import pandas as pd >>> df = pd.DataFrame({"A":[c for _ in range(5) for c in ["a", "b"]], "B":range(10)}) >>> df A B 0 a 0 1 b 1 2 a 2 3 b 3 4 a 4 5 b 5 6 a 6 7 b 7 8 a 8 9 b 9 >>> df.groupby("… <p> pandasのgroupbyを使って、平均や標準偏差を計算する方法は検索するとすぐ出てきます。</p><p> ただ、「そういうの良いから、項目ごとに使いやすいイテレータにしてまとめてくれよ!」と思うときがありますよね。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd &gt;&gt;&gt; df = pd.DataFrame({<span class="synConstant">&quot;A&quot;</span>:[c <span class="synStatement">for</span> _ <span class="synStatement">in</span> <span class="synIdentifier">range</span>(<span class="synConstant">5</span>) <span class="synStatement">for</span> c <span class="synStatement">in</span> [<span class="synConstant">&quot;a&quot;</span>, <span class="synConstant">&quot;b&quot;</span>]], <span class="synConstant">&quot;B&quot;</span>:<span class="synIdentifier">range</span>(<span class="synConstant">10</span>)}) &gt;&gt;&gt; df A B <span class="synConstant">0</span> a <span class="synConstant">0</span> <span class="synConstant">1</span> b <span class="synConstant">1</span> <span class="synConstant">2</span> a <span class="synConstant">2</span> <span class="synConstant">3</span> b <span class="synConstant">3</span> <span class="synConstant">4</span> a <span class="synConstant">4</span> <span class="synConstant">5</span> b <span class="synConstant">5</span> <span class="synConstant">6</span> a <span class="synConstant">6</span> <span class="synConstant">7</span> b <span class="synConstant">7</span> <span class="synConstant">8</span> a <span class="synConstant">8</span> <span class="synConstant">9</span> b <span class="synConstant">9</span> &gt;&gt;&gt; df.groupby(<span class="synConstant">&quot;A&quot;</span>) &lt;pandas.core.groupby.DataFrameGroupBy <span class="synIdentifier">object</span> at <span class="synConstant">0x7fd0742ec4e0</span>&gt; <span class="synComment"># よくわからない</span> </pre><p> とりあえず愚直にlistにしてみます。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synIdentifier">list</span>(df.groupby(<span class="synConstant">&quot;A&quot;</span>)) [(<span class="synConstant">'a'</span>, A B <span class="synConstant">0</span> a <span class="synConstant">0</span> <span class="synConstant">2</span> a <span class="synConstant">2</span> <span class="synConstant">4</span> a <span class="synConstant">4</span> <span class="synConstant">6</span> a <span class="synConstant">6</span> <span class="synConstant">8</span> a <span class="synConstant">8</span>), (<span class="synConstant">'b'</span>, A B <span class="synConstant">1</span> b <span class="synConstant">1</span> <span class="synConstant">3</span> b <span class="synConstant">3</span> <span class="synConstant">5</span> b <span class="synConstant">5</span> <span class="synConstant">7</span> b <span class="synConstant">7</span> <span class="synConstant">9</span> b <span class="synConstant">9</span>)] </pre><p> それぞれがデータフレームか。悪くはないけど、グルーピング対象の項目は要らないかな。</p><p> というか、特定の列だけあれば良いシチュエーションの方が多いでしょう。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synIdentifier">list</span>(df.groupby(<span class="synConstant">&quot;A&quot;</span>)[<span class="synConstant">&quot;B&quot;</span>]) [(<span class="synConstant">'a'</span>, <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">2</span> <span class="synConstant">2</span> <span class="synConstant">4</span> <span class="synConstant">4</span> <span class="synConstant">6</span> <span class="synConstant">6</span> <span class="synConstant">8</span> <span class="synConstant">8</span> Name: B, dtype: int64), (<span class="synConstant">'b'</span>, <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">3</span> <span class="synConstant">3</span> <span class="synConstant">5</span> <span class="synConstant">5</span> <span class="synConstant">7</span> <span class="synConstant">7</span> <span class="synConstant">9</span> <span class="synConstant">9</span> Name: B, dtype: int64)] </pre><p> けっこうそれらしくなってきた? 辞書にしてみましょう。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synIdentifier">dict</span>(<span class="synIdentifier">list</span>(df.groupby(<span class="synConstant">&quot;A&quot;</span>)[<span class="synConstant">&quot;B&quot;</span>]))[<span class="synConstant">&quot;a&quot;</span>] {<span class="synConstant">'a'</span>: <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">2</span> <span class="synConstant">2</span> <span class="synConstant">4</span> <span class="synConstant">4</span> <span class="synConstant">6</span> <span class="synConstant">6</span> <span class="synConstant">8</span> <span class="synConstant">8</span> Name: B, dtype: int64, <span class="synConstant">'b'</span>: <span class="synConstant">1</span> <span class="synConstant">1</span> <span class="synConstant">3</span> <span class="synConstant">3</span> <span class="synConstant">5</span> <span class="synConstant">5</span> <span class="synConstant">7</span> <span class="synConstant">7</span> <span class="synConstant">9</span> <span class="synConstant">9</span> Name: B, dtype: int64} &gt;&gt;&gt; <span class="synIdentifier">dict</span>(<span class="synIdentifier">list</span>(df.groupby(<span class="synConstant">&quot;A&quot;</span>)[<span class="synConstant">&quot;B&quot;</span>]))[<span class="synConstant">&quot;a&quot;</span>] <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">2</span> <span class="synConstant">2</span> <span class="synConstant">4</span> <span class="synConstant">4</span> <span class="synConstant">6</span> <span class="synConstant">6</span> <span class="synConstant">8</span> <span class="synConstant">8</span> Name: B, dtype: int64 </pre><p> Seriesはそんなに好きになれないので、スマートなコードでリストにできないか……と思って検索したら、こんなのがありました。</p><p><a href="https://stackoverflow.com/questions/22219004/grouping-rows-in-list-in-pandas-groupby">python - grouping rows in list in pandas groupby - Stack Overflow</a><br /> </p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; df.groupby(<span class="synConstant">&quot;A&quot;</span>)[<span class="synConstant">&quot;B&quot;</span>].<span class="synIdentifier">apply</span>(<span class="synIdentifier">list</span>) A a [<span class="synConstant">0</span>, <span class="synConstant">2</span>, <span class="synConstant">4</span>, <span class="synConstant">6</span>, <span class="synConstant">8</span>] b [<span class="synConstant">1</span>, <span class="synConstant">3</span>, <span class="synConstant">5</span>, <span class="synConstant">7</span>, <span class="synConstant">9</span>] Name: B, dtype: <span class="synIdentifier">object</span> </pre><p><br />  なるほどねー。これで良いでしょう。df.groupby("A")["B"].apply(list)["a"]とかで取り出せるみたいだし。</p> hayataka2049 【python】sklearnのVarianceThresholdを試してみる hatenablog://entry/17391345971653696438 2018-06-13T16:33:47+09:00 2019-06-29T20:03:10+09:00 はじめに VarianceThresholdは名前の通り、分散がしきい値以下の特徴量を捨てます。sklearn.feature_selection.VarianceThreshold — scikit-learn 0.20.2 documentation これといってすごいところはありませんが、気楽に使えそうなので試してみました。 目次 はじめに とりあえず試す 分類を試してみる まとめ スポンサーリンク (adsbygoogle = window.adsbygoogle || []).push({}); とりあえず試す しきい値の設定でどれだけ特徴量のshapeが減るか見てみました。 データ… <div class="section"> <h3 id="はじめに">はじめに</h3> <p> VarianceThresholdは名前の通り、分散がしきい値以下の特徴量を捨てます。</p><p><a href="http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.VarianceThreshold.html">sklearn.feature_selection.VarianceThreshold &mdash; scikit-learn 0.20.2 documentation</a></p><p> これといってすごいところはありませんが、気楽に使えそうなので試してみました。</p><p> 目次</p> <ul class="table-of-contents"> <li><a href="#はじめに">はじめに</a></li> <li><a href="#とりあえず試す">とりあえず試す</a></li> <li><a href="#分類を試してみる">分類を試してみる</a></li> <li><a href="#まとめ">まとめ</a></li> </ul><p><span style="font-size: 80%">スポンサーリンク</span><br /> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script></p> <p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-6261827798827777" data-ad-slot="1744230936" data-ad-format="auto" data-full-width-responsive="true"></ins><br /> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script></p><br /> <p></p> </div> <div class="section"> <h3 id="とりあえず試す">とりあえず試す</h3> <p> しきい値の設定でどれだけ特徴量のshapeが減るか見てみました。</p><p> データは<a href="http://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_20newsgroups.html">20newsgroups</a>です。<br /> <a href="http://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html">Pipeline</a>にしてあるのは、あとでこれを使って分類のチューニングをしてみるためです。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">from</span> sklearn.datasets <span class="synPreProc">import</span> fetch_20newsgroups <span class="synPreProc">from</span> sklearn.feature_extraction.text <span class="synPreProc">import</span> CountVectorizer <span class="synPreProc">from</span> sklearn.feature_selection <span class="synPreProc">import</span> VarianceThreshold <span class="synPreProc">from</span> sklearn.pipeline <span class="synPreProc">import</span> Pipeline <span class="synStatement">def</span> <span class="synIdentifier">test_shape</span>(): news20 = fetch_20newsgroups() cv = CountVectorizer(min_df=<span class="synConstant">0.005</span>, max_df=<span class="synConstant">0.5</span>, stop_words=<span class="synConstant">&quot;english&quot;</span>) vth = VarianceThreshold() pl = Pipeline([(<span class="synConstant">&quot;cv&quot;</span>, cv), (<span class="synConstant">&quot;vth&quot;</span>, vth)]) <span class="synStatement">for</span> v <span class="synStatement">in</span> [<span class="synConstant">0.0</span>,<span class="synConstant">0.05</span>,<span class="synConstant">0.1</span>,<span class="synConstant">0.15</span>]: pl.set_params(vth__threshold=v) <span class="synIdentifier">print</span>(pl.fit_transform(news20.data).shape) <span class="synStatement">if</span> __name__ == <span class="synConstant">&quot;__main__&quot;</span>: test_shape() </pre><p> 関連記事:</p> <ul> <li><a href="https://www.haya-programming.com/entry/2018/02/19/200006">&#x3010;python&#x3011;sklearn&#x306E;fetch_20newsgroups&#x3067;&#x6587;&#x66F8;&#x5206;&#x985E;&#x3092;&#x8A66;&#x3059;(1) - &#x9759;&#x304B;&#x306A;&#x308B;&#x540D;&#x8F9E;</a></li> <li><a href="https://www.haya-programming.com/entry/2018/02/22/234011">&#x3010;python&#x3011;sklearn&#x306E;Pipeline&#x3092;&#x4F7F;&#x3046;&#x3068;&#x3067;&#x304D;&#x308B;&#x3053;&#x3068; - &#x9759;&#x304B;&#x306A;&#x308B;&#x540D;&#x8F9E;</a></li> <li><a href="https://www.haya-programming.com/entry/2018/02/25/044525">&#x3010;python&#x3011;sklearn&#x306E;CountVectorizer&#x306E;&#x4F7F;&#x3044;&#x65B9; - &#x9759;&#x304B;&#x306A;&#x308B;&#x540D;&#x8F9E;</a></li> </ul><p><br />  結果は、</p> <pre class="code" data-lang="" data-unlink>(11314, 3705) (11314, 1476) (11314, 859) (11314, 573)</pre><p> なるほど。<br />  (実際にはいろいろ試してちょうど良いshapeの減り具合になる値を探しています。これを使うならそういう作業が必要になると思います)</p> </div> <div class="section"> <h3 id="分類を試してみる">分類を試してみる</h3> <p> これをうまく設定すると、分類精度が上がったりするのでしょうか?</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd <span class="synPreProc">from</span> sklearn.datasets <span class="synPreProc">import</span> fetch_20newsgroups <span class="synPreProc">from</span> sklearn.feature_extraction.text <span class="synPreProc">import</span> CountVectorizer <span class="synPreProc">from</span> sklearn.preprocessing <span class="synPreProc">import</span> FunctionTransformer <span class="synPreProc">from</span> sklearn.feature_selection <span class="synPreProc">import</span> VarianceThreshold <span class="synPreProc">from</span> sklearn.naive_bayes <span class="synPreProc">import</span> GaussianNB <span class="synPreProc">from</span> sklearn.pipeline <span class="synPreProc">import</span> Pipeline <span class="synPreProc">from</span> sklearn.model_selection <span class="synPreProc">import</span> GridSearchCV <span class="synStatement">def</span> <span class="synIdentifier">convert</span>(x): <span class="synStatement">return</span> x.toarray() <span class="synStatement">def</span> <span class="synIdentifier">test_best_v</span>(): news20 = fetch_20newsgroups() cv = CountVectorizer(min_df=<span class="synConstant">0.005</span>, max_df=<span class="synConstant">0.5</span>, stop_words=<span class="synConstant">&quot;english&quot;</span>) vth = VarianceThreshold() sparse_to_dense = FunctionTransformer(func=convert, accept_sparse=<span class="synIdentifier">True</span>) gnb = GaussianNB() pl = Pipeline([(<span class="synConstant">&quot;cv&quot;</span>, cv), (<span class="synConstant">&quot;vth&quot;</span>, vth), (<span class="synConstant">&quot;s2d&quot;</span>, sparse_to_dense), (<span class="synConstant">&quot;gnb&quot;</span>, gnb)]) params = {<span class="synConstant">&quot;vth__threshold&quot;</span>:[<span class="synConstant">0.0</span>,<span class="synConstant">0.05</span>,<span class="synConstant">0.1</span>,<span class="synConstant">0.15</span>]} clf = GridSearchCV(pl, params, return_train_score=<span class="synIdentifier">False</span>, n_jobs=-<span class="synConstant">1</span>) clf.fit(news20.data, news20.target) cv_result_df = pd.DataFrame(clf.cv_results_) df = cv_result_df[[<span class="synConstant">&quot;param_vth__threshold&quot;</span>, <span class="synConstant">&quot;mean_score_time&quot;</span>, <span class="synConstant">&quot;mean_test_score&quot;</span>]] <span class="synIdentifier">print</span>(df) <span class="synStatement">if</span> __name__ == <span class="synConstant">&quot;__main__&quot;</span>: test_best_v() </pre><p> ただ単にナイーブベイズに入れて性能を見ているだけですが、かなり色々なテクニックを使っているコードなので、初見だと読みづらいと思います。</p> <ul> <li>FunctionTransformer:</li> </ul><p> ナイーブベイズが疎行列を受け付けてくれないので変換している。こんな関数ラムダ式で良いじゃんと思う向きもあるかもしれませんが、GridSearchCVでn_jobs=-1を指定するためにはトップレベル関数として定義してあげる必要があります(中でpickleを使うので)</p> <ul> <li>GridSearchCV:</li> </ul><p> return_train_score=Falseにすると速くなります。</p> <ul> <li>pd.DataFrame</li> </ul><p> GridSearchCV.cv_results_はそのままpandas.DataFrameに変換できると<a href="http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html">&#x30C9;&#x30AD;&#x30E5;&#x30E1;&#x30F3;&#x30C8;&#x306B;&#x66F8;&#x3044;&#x3066;&#x3042;&#x308B;&#x306E;&#x3067;</a>、それを使ってpandasで取り扱っています。</p><p> 走らせた結果は、</p> <pre class="code lang-python" data-lang="python" data-unlink> param_vth__threshold mean_score_time mean_test_score <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">9.646958</span> <span class="synConstant">0.656178</span> <span class="synConstant">1</span> <span class="synConstant">0.05</span> <span class="synConstant">4.504278</span> <span class="synConstant">0.587149</span> <span class="synConstant">2</span> <span class="synConstant">0.1</span> <span class="synConstant">2.804257</span> <span class="synConstant">0.512551</span> <span class="synConstant">3</span> <span class="synConstant">0.15</span> <span class="synConstant">1.909767</span> <span class="synConstant">0.453244</span> </pre><p> 改善する訳ではない。CountVectorizerのmin_dfで予めゴミ変数を削っていること、スパースな空間なので分散が低くてもそれはそれで構わず、ナイーブベイズが意外とスパースに強いのも相まって優秀に働いていることが原因でしょう。</p><p> それより注目すべきはmean_score_timeで、今回のデータで変数を削っていくと、しきい値を0.05上げるたびに、0.07ポイントくらいの性能低下と引き換えに半減するような傾向です。性能と時間のトレードオフになったときは、これをいじって調整する手はあるのかも。</p> </div> <div class="section"> <h3 id="まとめ">まとめ</h3> <p> 微妙といえば微妙だし、データによっては効くのかもしれない気もします。とりあえず確実に速くはなります。</p><p> 性能はあまり重視していないとき、気楽に変数を捨てて速くするのに使えそうです。</p> </div> hayataka2049 【python】pandasのDataFrameをLaTeX出力 hatenablog://entry/17391345971649542688 2018-05-31T02:00:09+09:00 2018-11-28T01:45:48+09:00 そんな機能があるらしい。DataFrame.to_latex()という名前のメソッドである。pandas.DataFrame.to_latex — pandas 0.21.1 documentation これが使えると何かの役に立つかもしれないので、使い物になるかどうか確認してみる。 お試し とりあえず、てきとーにdfを作ってみる。中身に意味はないけど、意味のないdfをできるだけ手っ取り早く作りたかったのでnumpy配列から作っている。*1 >>> import numpy as np >>> import pandas as pd >>> df = pd.DataFrame(np.arang… <p> そんな機能があるらしい。DataFrame.to_latex()という名前のメソッドである。</p><p><a href="http://pandas.pydata.org/pandas-docs/version/0.21/generated/pandas.DataFrame.to_latex.html">pandas.DataFrame.to_latex &mdash; pandas 0.21.1 documentation</a></p><p> これが使えると何かの役に立つかもしれないので、使い物になるかどうか確認してみる。</p> <div class="section"> <h3>お試し</h3> <p> とりあえず、てきとーにdfを作ってみる。中身に意味はないけど、意味のないdfをできるだけ手っ取り早く作りたかったのでnumpy配列から作っている。<a href="#f-dddc0852" name="fn-dddc0852" title="pandasの機能を試すときって、試すためのdf作るのがそもそも面倒くさいということが往々にしてある。みんなはどうやってるんだろうか">*1</a><br /> </p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> numpy <span class="synStatement">as</span> np &gt;&gt;&gt; <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd &gt;&gt;&gt; df = pd.DataFrame(np.arange(<span class="synConstant">32</span>).reshape(<span class="synConstant">8</span>,<span class="synConstant">4</span>), columns=<span class="synIdentifier">list</span>(<span class="synConstant">&quot;abcd&quot;</span>)) &gt;&gt;&gt; df a b c d <span class="synConstant">0</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">2</span> <span class="synConstant">3</span> <span class="synConstant">1</span> <span class="synConstant">4</span> <span class="synConstant">5</span> <span class="synConstant">6</span> <span class="synConstant">7</span> <span class="synConstant">2</span> <span class="synConstant">8</span> <span class="synConstant">9</span> <span class="synConstant">10</span> <span class="synConstant">11</span> <span class="synConstant">3</span> <span class="synConstant">12</span> <span class="synConstant">13</span> <span class="synConstant">14</span> <span class="synConstant">15</span> <span class="synConstant">4</span> <span class="synConstant">16</span> <span class="synConstant">17</span> <span class="synConstant">18</span> <span class="synConstant">19</span> <span class="synConstant">5</span> <span class="synConstant">20</span> <span class="synConstant">21</span> <span class="synConstant">22</span> <span class="synConstant">23</span> <span class="synConstant">6</span> <span class="synConstant">24</span> <span class="synConstant">25</span> <span class="synConstant">26</span> <span class="synConstant">27</span> <span class="synConstant">7</span> <span class="synConstant">28</span> <span class="synConstant">29</span> <span class="synConstant">30</span> <span class="synConstant">31</span> </pre><p> そのまま何も考えず、to_latex()を呼ぶ。strで返っても都合が悪いのでprintしてみる。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synIdentifier">print</span>(df.to_latex()) \begin{tabular}{lrrrr} \toprule {} &amp; a &amp; b &amp; c &amp; d \<span class="synSpecial">\</span> \midrule <span class="synConstant">0</span> &amp; <span class="synConstant">0</span> &amp; <span class="synConstant">1</span> &amp; <span class="synConstant">2</span> &amp; <span class="synConstant">3</span> \<span class="synSpecial">\</span> <span class="synConstant">1</span> &amp; <span class="synConstant">4</span> &amp; <span class="synConstant">5</span> &amp; <span class="synConstant">6</span> &amp; <span class="synConstant">7</span> \<span class="synSpecial">\</span> <span class="synConstant">2</span> &amp; <span class="synConstant">8</span> &amp; <span class="synConstant">9</span> &amp; <span class="synConstant">10</span> &amp; <span class="synConstant">11</span> \<span class="synSpecial">\</span> <span class="synConstant">3</span> &amp; <span class="synConstant">12</span> &amp; <span class="synConstant">13</span> &amp; <span class="synConstant">14</span> &amp; <span class="synConstant">15</span> \<span class="synSpecial">\</span> <span class="synConstant">4</span> &amp; <span class="synConstant">16</span> &amp; <span class="synConstant">17</span> &amp; <span class="synConstant">18</span> &amp; <span class="synConstant">19</span> \<span class="synSpecial">\</span> <span class="synConstant">5</span> &amp; <span class="synConstant">20</span> &amp; <span class="synConstant">21</span> &amp; <span class="synConstant">22</span> &amp; <span class="synConstant">23</span> \<span class="synSpecial">\</span> <span class="synConstant">6</span> &amp; <span class="synConstant">24</span> &amp; <span class="synConstant">25</span> &amp; <span class="synConstant">26</span> &amp; <span class="synConstant">27</span> \<span class="synSpecial">\</span> <span class="synConstant">7</span> &amp; <span class="synConstant">28</span> &amp; <span class="synConstant">29</span> &amp; <span class="synConstant">30</span> &amp; <span class="synConstant">31</span> \<span class="synSpecial">\</span> \bottomrule \end{tabular} </pre><p> そしたらこれを別途作ったTeXのソースに貼る。ドキュメント曰く、</p> <blockquote> <p>Render an object to a tabular environment table. You can splice this into a LaTeX document. <b>Requires \usepackage{booktabs}.</b></p> </blockquote> <p> (強調は僕が勝手に付けたもの)</p><p> ということらしい。とにかく次のようなTeXファイルを作ってみた。</p> <pre class="code lang-tex" data-lang="tex" data-unlink><span class="synStatement">\documentclass</span><span class="synSpecial">{</span><span class="synPreProc">jsarticle</span><span class="synSpecial">}</span> <span class="synStatement">\usepackage</span><span class="synSpecial">{booktabs}</span> <span class="synPreProc">\begin{document}</span> <span class="synStatement">\begin</span><span class="synSpecial">{</span><span class="synPreProc">table</span><span class="synSpecial">}[</span>h<span class="synSpecial">]</span> <span class="synStatement">\begin</span><span class="synSpecial">{</span><span class="synPreProc">tabular</span><span class="synSpecial">}{</span>lrrrr<span class="synSpecial">}</span> <span class="synStatement">\toprule</span> <span class="synSpecial">{}</span> <span class="synSpecial">&amp;</span> a <span class="synSpecial">&amp;</span> b <span class="synSpecial">&amp;</span> c <span class="synSpecial">&amp;</span> d <span class="synSpecial">\\</span> <span class="synStatement">\midrule</span> 0 <span class="synSpecial">&amp;</span> 0 <span class="synSpecial">&amp;</span> 1 <span class="synSpecial">&amp;</span> 2 <span class="synSpecial">&amp;</span> 3 <span class="synSpecial">\\</span> 1 <span class="synSpecial">&amp;</span> 4 <span class="synSpecial">&amp;</span> 5 <span class="synSpecial">&amp;</span> 6 <span class="synSpecial">&amp;</span> 7 <span class="synSpecial">\\</span> 2 <span class="synSpecial">&amp;</span> 8 <span class="synSpecial">&amp;</span> 9 <span class="synSpecial">&amp;</span> 10 <span class="synSpecial">&amp;</span> 11 <span class="synSpecial">\\</span> 3 <span class="synSpecial">&amp;</span> 12 <span class="synSpecial">&amp;</span> 13 <span class="synSpecial">&amp;</span> 14 <span class="synSpecial">&amp;</span> 15 <span class="synSpecial">\\</span> 4 <span class="synSpecial">&amp;</span> 16 <span class="synSpecial">&amp;</span> 17 <span class="synSpecial">&amp;</span> 18 <span class="synSpecial">&amp;</span> 19 <span class="synSpecial">\\</span> 5 <span class="synSpecial">&amp;</span> 20 <span class="synSpecial">&amp;</span> 21 <span class="synSpecial">&amp;</span> 22 <span class="synSpecial">&amp;</span> 23 <span class="synSpecial">\\</span> 6 <span class="synSpecial">&amp;</span> 24 <span class="synSpecial">&amp;</span> 25 <span class="synSpecial">&amp;</span> 26 <span class="synSpecial">&amp;</span> 27 <span class="synSpecial">\\</span> 7 <span class="synSpecial">&amp;</span> 28 <span class="synSpecial">&amp;</span> 29 <span class="synSpecial">&amp;</span> 30 <span class="synSpecial">&amp;</span> 31 <span class="synSpecial">\\</span> <span class="synStatement">\bottomrule</span> <span class="synStatement">\end</span><span class="synSpecial">{</span><span class="synPreProc">tabular</span><span class="synSpecial">}</span> <span class="synStatement">\end</span><span class="synSpecial">{</span><span class="synPreProc">table</span><span class="synSpecial">}</span> <span class="synPreProc">\end{document}</span> </pre><p> TeXとかよくわからないけど、これでコンパイルできてこんな結果が得られた。</p><p><figure class="figure-image figure-image-fotolife" title="できた表"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hayataka2049/20180531/20180531012934.png" alt="&#x3067;&#x304D;&#x305F;&#x8868;" title="f:id:hayataka2049:20180531012934p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption></figcaption></figure></p><p> なるほど、できてますね。</p><p> フォーマットは、論文でよく見かける罫線の少ない表です。カッコいい気もするし、罫線多めのちょいダサな表の方が安心感があって良いような気もするという、人によって好みの分かれる奴です。</p> </div> <div class="section"> <h3>カスタマイズしてみよう</h3> <p> たかがto_latex()なのに、なんかいろいろ引数があります。公式をまとめておきます。</p> <ul> <li>bold_rows : boolean, default False</li> </ul><p> インデックス列の文字がboldになる</p> <ul> <li>column_format : str, default None</li> </ul><p> \begin{tabular}{}の{}の中に入る列の書式を文字列で渡す</p> <ul> <li>longtable : boolean, default will be read from the pandas config module Default: False</li> </ul><p> TeXのlongtableだって。参考(外部サイト):<a href="https://qiita.com/siquare/items/e92786c85b5f4ad7753d">[LaTeX]&#x9577;&#x3044;&#x8868;&#x3092;&#x8868;&#x793A;&#x3059;&#x308B; - Qiita</a><br /> </p> <ul> <li>escape : boolean, default will be read from the pandas config module Default: True.</li> </ul><p> エスケープがうまく効くかどうかにかかってくるんだと思う</p> <ul> <li>encoding : str, default None</li> </ul><p> 何も指定しないとpython2はascii, python3はutf-8になるらしい。</p> <ul> <li>decimal : string, default ‘.’</li> </ul><p> Character recognized as decimal separator, e.g. ‘,’ in Europe.<br />  (説明を読んでもよくわからん)</p> <ul> <li>multicolumn : boolean, default True</li> </ul><p>Use multicolumn to enhance MultiIndex columns. The default will be read from the config module.</p> <ul> <li>multicolumn_format : str, default ‘l’</li> </ul><p>The alignment for multicolumns, similar to column_format The default will be read from the config module.</p> <ul> <li>multirow : boolean, default False</li> </ul><p>Use multirow to enhance MultiIndex rows. Requires adding a \usepackage{multirow} to your LaTeX preamble. Will print centered labels (instead of top-aligned) across the contained rows, separating groups via clines. The default will be read from the pandas config module.</p><p> 上の3つは使い方がよくわからない。まあ、たぶん使えば使えるんだろう。</p><p> せっかくなので、インデックス列bold、罫線多めな表を作ってみようと思う。見た目がダサくなるはずだ。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synIdentifier">print</span>(df.to_latex(bold_rows=<span class="synIdentifier">True</span>, column_format=<span class="synConstant">&quot;|l|l|l|l|&quot;</span>)) \begin{tabular}{|l|l|l|l|} \toprule {} &amp; a &amp; b &amp; c &amp; d \<span class="synSpecial">\</span> \midrule \textbf{<span class="synConstant">0</span>} &amp; <span class="synConstant">0</span> &amp; <span class="synConstant">1</span> &amp; <span class="synConstant">2</span> &amp; <span class="synConstant">3</span> \<span class="synSpecial">\</span> \textbf{<span class="synConstant">1</span>} &amp; <span class="synConstant">4</span> &amp; <span class="synConstant">5</span> &amp; <span class="synConstant">6</span> &amp; <span class="synConstant">7</span> \<span class="synSpecial">\</span> \textbf{<span class="synConstant">2</span>} &amp; <span class="synConstant">8</span> &amp; <span class="synConstant">9</span> &amp; <span class="synConstant">10</span> &amp; <span class="synConstant">11</span> \<span class="synSpecial">\</span> \textbf{<span class="synConstant">3</span>} &amp; <span class="synConstant">12</span> &amp; <span class="synConstant">13</span> &amp; <span class="synConstant">14</span> &amp; <span class="synConstant">15</span> \<span class="synSpecial">\</span> \textbf{<span class="synConstant">4</span>} &amp; <span class="synConstant">16</span> &amp; <span class="synConstant">17</span> &amp; <span class="synConstant">18</span> &amp; <span class="synConstant">19</span> \<span class="synSpecial">\</span> \textbf{<span class="synConstant">5</span>} &amp; <span class="synConstant">20</span> &amp; <span class="synConstant">21</span> &amp; <span class="synConstant">22</span> &amp; <span class="synConstant">23</span> \<span class="synSpecial">\</span> \textbf{<span class="synConstant">6</span>} &amp; <span class="synConstant">24</span> &amp; <span class="synConstant">25</span> &amp; <span class="synConstant">26</span> &amp; <span class="synConstant">27</span> \<span class="synSpecial">\</span> \textbf{<span class="synConstant">7</span>} &amp; <span class="synConstant">28</span> &amp; <span class="synConstant">29</span> &amp; <span class="synConstant">30</span> &amp; <span class="synConstant">31</span> \<span class="synSpecial">\</span> \bottomrule \end{tabular} </pre><pre class="code lang-tex" data-lang="tex" data-unlink><span class="synStatement">\documentclass</span><span class="synSpecial">{</span><span class="synPreProc">jsarticle</span><span class="synSpecial">}</span> <span class="synStatement">\usepackage</span><span class="synSpecial">{booktabs}</span> <span class="synPreProc">\begin{document}</span> <span class="synStatement">\begin</span><span class="synSpecial">{</span><span class="synPreProc">table</span><span class="synSpecial">}[</span>h<span class="synSpecial">]</span> <span class="synStatement">\begin</span><span class="synSpecial">{</span><span class="synPreProc">tabular</span><span class="synSpecial">}{</span>|l|l|l|l|l|<span class="synSpecial">}</span> <span class="synStatement">\toprule</span> <span class="synSpecial">{}</span> <span class="synSpecial">&amp;</span> a <span class="synSpecial">&amp;</span> b <span class="synSpecial">&amp;</span> c <span class="synSpecial">&amp;</span> d <span class="synSpecial">\\</span> <span class="synStatement">\midrule</span> <span class="synType">\textbf{</span>0<span class="synType">}</span> <span class="synSpecial">&amp;</span> 0 <span class="synSpecial">&amp;</span> 1 <span class="synSpecial">&amp;</span> 2 <span class="synSpecial">&amp;</span> 3 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>1<span class="synType">}</span> <span class="synSpecial">&amp;</span> 4 <span class="synSpecial">&amp;</span> 5 <span class="synSpecial">&amp;</span> 6 <span class="synSpecial">&amp;</span> 7 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>2<span class="synType">}</span> <span class="synSpecial">&amp;</span> 8 <span class="synSpecial">&amp;</span> 9 <span class="synSpecial">&amp;</span> 10 <span class="synSpecial">&amp;</span> 11 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>3<span class="synType">}</span> <span class="synSpecial">&amp;</span> 12 <span class="synSpecial">&amp;</span> 13 <span class="synSpecial">&amp;</span> 14 <span class="synSpecial">&amp;</span> 15 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>4<span class="synType">}</span> <span class="synSpecial">&amp;</span> 16 <span class="synSpecial">&amp;</span> 17 <span class="synSpecial">&amp;</span> 18 <span class="synSpecial">&amp;</span> 19 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>5<span class="synType">}</span> <span class="synSpecial">&amp;</span> 20 <span class="synSpecial">&amp;</span> 21 <span class="synSpecial">&amp;</span> 22 <span class="synSpecial">&amp;</span> 23 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>6<span class="synType">}</span> <span class="synSpecial">&amp;</span> 24 <span class="synSpecial">&amp;</span> 25 <span class="synSpecial">&amp;</span> 26 <span class="synSpecial">&amp;</span> 27 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>7<span class="synType">}</span> <span class="synSpecial">&amp;</span> 28 <span class="synSpecial">&amp;</span> 29 <span class="synSpecial">&amp;</span> 30 <span class="synSpecial">&amp;</span> 31 <span class="synSpecial">\\</span> <span class="synStatement">\bottomrule</span> <span class="synStatement">\end</span><span class="synSpecial">{</span><span class="synPreProc">tabular</span><span class="synSpecial">}</span> <span class="synStatement">\end</span><span class="synSpecial">{</span><span class="synPreProc">table</span><span class="synSpecial">}</span> <span class="synPreProc">\end{document}</span> </pre><p> 結果は、</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hayataka2049/20180531/20180531015049.png" alt="f:id:hayataka2049:20180531015049p:plain" title="f:id:hayataka2049:20180531015049p:plain" class="hatena-fotolife" itemprop="image"></span></p><p> なんか思ってたのと違う・・・\*rule系と縦罫線の相性が悪いので、\hlineに変えてみる(TeXソースを直接いじって)。</p> <pre class="code lang-tex" data-lang="tex" data-unlink><span class="synStatement">\documentclass</span><span class="synSpecial">{</span><span class="synPreProc">jsarticle</span><span class="synSpecial">}</span> <span class="synStatement">\usepackage</span><span class="synSpecial">{booktabs}</span> <span class="synPreProc">\begin{document}</span> <span class="synStatement">\begin</span><span class="synSpecial">{</span><span class="synPreProc">table</span><span class="synSpecial">}[</span>h<span class="synSpecial">]</span> <span class="synStatement">\begin</span><span class="synSpecial">{</span><span class="synPreProc">tabular</span><span class="synSpecial">}{</span>|l|l|l|l|l|<span class="synSpecial">}</span> <span class="synStatement">\hline</span> <span class="synSpecial">{}</span> <span class="synSpecial">&amp;</span> a <span class="synSpecial">&amp;</span> b <span class="synSpecial">&amp;</span> c <span class="synSpecial">&amp;</span> d <span class="synSpecial">\\</span> <span class="synStatement">\hline</span> <span class="synType">\textbf{</span>0<span class="synType">}</span> <span class="synSpecial">&amp;</span> 0 <span class="synSpecial">&amp;</span> 1 <span class="synSpecial">&amp;</span> 2 <span class="synSpecial">&amp;</span> 3 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>1<span class="synType">}</span> <span class="synSpecial">&amp;</span> 4 <span class="synSpecial">&amp;</span> 5 <span class="synSpecial">&amp;</span> 6 <span class="synSpecial">&amp;</span> 7 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>2<span class="synType">}</span> <span class="synSpecial">&amp;</span> 8 <span class="synSpecial">&amp;</span> 9 <span class="synSpecial">&amp;</span> 10 <span class="synSpecial">&amp;</span> 11 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>3<span class="synType">}</span> <span class="synSpecial">&amp;</span> 12 <span class="synSpecial">&amp;</span> 13 <span class="synSpecial">&amp;</span> 14 <span class="synSpecial">&amp;</span> 15 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>4<span class="synType">}</span> <span class="synSpecial">&amp;</span> 16 <span class="synSpecial">&amp;</span> 17 <span class="synSpecial">&amp;</span> 18 <span class="synSpecial">&amp;</span> 19 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>5<span class="synType">}</span> <span class="synSpecial">&amp;</span> 20 <span class="synSpecial">&amp;</span> 21 <span class="synSpecial">&amp;</span> 22 <span class="synSpecial">&amp;</span> 23 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>6<span class="synType">}</span> <span class="synSpecial">&amp;</span> 24 <span class="synSpecial">&amp;</span> 25 <span class="synSpecial">&amp;</span> 26 <span class="synSpecial">&amp;</span> 27 <span class="synSpecial">\\</span> <span class="synType">\textbf{</span>7<span class="synType">}</span> <span class="synSpecial">&amp;</span> 28 <span class="synSpecial">&amp;</span> 29 <span class="synSpecial">&amp;</span> 30 <span class="synSpecial">&amp;</span> 31 <span class="synSpecial">\\</span> <span class="synStatement">\hline</span> <span class="synStatement">\end</span><span class="synSpecial">{</span><span class="synPreProc">tabular</span><span class="synSpecial">}</span> <span class="synStatement">\end</span><span class="synSpecial">{</span><span class="synPreProc">table</span><span class="synSpecial">}</span> <span class="synPreProc">\end{document}</span> </pre><p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hayataka2049/20180531/20180531015313.png" alt="f:id:hayataka2049:20180531015313p:plain" title="f:id:hayataka2049:20180531015313p:plain" class="hatena-fotolife" itemprop="image"></span></p><p> これは期待通りの結果だが、わざわざpandasが出力されるものをいじってこうしたいか? と考えると、デフォルトで吐き出されたものをそのまま使った方が潔いかもしれない。</p> </div> <div class="section"> <h3>まとめ</h3> <p> 使えるか? というと、とても微妙な機能ですが、考えようによっては、データをDataFrameに入れさえすれば、TeXの表組みと格闘する必要が一切なくなります。<br /> (デフォルトで出てきた表の見た目に満足できれば)</p><p> なので、それなりにおすすめです。</p> </div><div class="footnote"> <p class="footnote"><a href="#fn-dddc0852" name="f-dddc0852" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">pandasの機能を試すときって、試すためのdf作るのがそもそも面倒くさいということが往々にしてある。みんなはどうやってるんだろうか</span></p> </div> hayataka2049 【python】pandasでデータを標準得点(z得点)に変換 hatenablog://entry/17391345971638134742 2018-04-24T22:36:26+09:00 2019-02-21T01:46:53+09:00 データの正規化(標準化)をpandasでもやってみる。 正規化、標準化とは、データを分散1、平均0に変換する操作である。スポンサーリンク (adsbygoogle = window.adsbygoogle || []).push({}); 自分で書いてもできるが、scipyの関数を使うと簡単にできる。 >>> import pandas as pd >>> df = pd.DataFrame([[1,2,3,4,5,6], [6,5,4,3,2,1], [0,1,2,3,4,5], [5,4,3,2,1,0]], columns=[*"ABCDEF"]) >>> df.apply(stats.… <p> データの正規化(標準化)をpandasでもやってみる。</p><p> 正規化、標準化とは、データを分散1、平均0に変換する操作である。</p><p><span style="font-size: 80%">スポンサーリンク</span><br /> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script></p> <p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-6261827798827777" data-ad-slot="1744230936" data-ad-format="auto" data-full-width-responsive="true"></ins><br /> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script></p><br /> <br /> <p> 自分で書いてもできるが、scipyの関数を使うと簡単にできる。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd &gt;&gt;&gt; df = pd.DataFrame([[<span class="synConstant">1</span>,<span class="synConstant">2</span>,<span class="synConstant">3</span>,<span class="synConstant">4</span>,<span class="synConstant">5</span>,<span class="synConstant">6</span>], [<span class="synConstant">6</span>,<span class="synConstant">5</span>,<span class="synConstant">4</span>,<span class="synConstant">3</span>,<span class="synConstant">2</span>,<span class="synConstant">1</span>], [<span class="synConstant">0</span>,<span class="synConstant">1</span>,<span class="synConstant">2</span>,<span class="synConstant">3</span>,<span class="synConstant">4</span>,<span class="synConstant">5</span>], [<span class="synConstant">5</span>,<span class="synConstant">4</span>,<span class="synConstant">3</span>,<span class="synConstant">2</span>,<span class="synConstant">1</span>,<span class="synConstant">0</span>]], columns=[*<span class="synConstant">&quot;ABCDEF&quot;</span>]) &gt;&gt;&gt; df.<span class="synIdentifier">apply</span>(stats.zscore, axis=<span class="synConstant">0</span>) A B C D E F <span class="synConstant">0</span> -<span class="synConstant">0.784465</span> -<span class="synConstant">0.632456</span> <span class="synConstant">0.000000</span> <span class="synConstant">1.414214</span> <span class="synConstant">1.264911</span> <span class="synConstant">1.176697</span> <span class="synConstant">1</span> <span class="synConstant">1.176697</span> <span class="synConstant">1.264911</span> <span class="synConstant">1.414214</span> <span class="synConstant">0.000000</span> -<span class="synConstant">0.632456</span> -<span class="synConstant">0.784465</span> <span class="synConstant">2</span> -<span class="synConstant">1.176697</span> -<span class="synConstant">1.264911</span> -<span class="synConstant">1.414214</span> <span class="synConstant">0.000000</span> <span class="synConstant">0.632456</span> <span class="synConstant">0.784465</span> <span class="synConstant">3</span> <span class="synConstant">0.784465</span> <span class="synConstant">0.632456</span> <span class="synConstant">0.000000</span> -<span class="synConstant">1.414214</span> -<span class="synConstant">1.264911</span> -<span class="synConstant">1.176697</span> &gt;&gt;&gt; df.<span class="synIdentifier">apply</span>(stats.zscore, axis=<span class="synConstant">1</span>) A B C D E F <span class="synConstant">0</span> -<span class="synConstant">1.46385</span> -<span class="synConstant">0.87831</span> -<span class="synConstant">0.29277</span> <span class="synConstant">0.29277</span> <span class="synConstant">0.87831</span> <span class="synConstant">1.46385</span> <span class="synConstant">1</span> <span class="synConstant">1.46385</span> <span class="synConstant">0.87831</span> <span class="synConstant">0.29277</span> -<span class="synConstant">0.29277</span> -<span class="synConstant">0.87831</span> -<span class="synConstant">1.46385</span> <span class="synConstant">2</span> -<span class="synConstant">1.46385</span> -<span class="synConstant">0.87831</span> -<span class="synConstant">0.29277</span> <span class="synConstant">0.29277</span> <span class="synConstant">0.87831</span> <span class="synConstant">1.46385</span> <span class="synConstant">3</span> <span class="synConstant">1.46385</span> <span class="synConstant">0.87831</span> <span class="synConstant">0.29277</span> -<span class="synConstant">0.29277</span> -<span class="synConstant">0.87831</span> -<span class="synConstant">1.46385</span> </pre><p> axis=0だと列で計算した標準得点、axis=1で行で計算した標準得点になる。</p> hayataka2049 【python】pandasでDataFrameの平均と標準偏差を計算する方法 hatenablog://entry/17391345971638128680 2018-04-24T22:19:33+09:00 2019-07-15T01:28:12+09:00 概要 DataFrameから平均と標準偏差を計算する方法をメモしておきます。 目次 概要 列の平均と標準偏差を計算したい 行の平均と標準偏差を計算したい 特定の列・行だけ取り出してから計算する describeメソッドで全体の雰囲気を掴む 列の平均と標準偏差を計算したい とても簡単にできます。 >>> import pandas as pd >>> df = pd.DataFrame([[1,2,3,4,5,6], [6,5,4,3,2,1], [0,1,2,3,4,5], [5,4,3,2,1,0]], columns=[*"ABCDEF"]) >>> df.mean() A 3.0 B 3… <div class="section"> <h3 id="概要">概要</h3> <p> DataFrameから平均と標準偏差を計算する方法をメモしておきます。</p><p> 目次</p> <ul class="table-of-contents"> <li><a href="#概要">概要</a></li> <li><a href="#列の平均と標準偏差を計算したい">列の平均と標準偏差を計算したい</a></li> <li><a href="#行の平均と標準偏差を計算したい">行の平均と標準偏差を計算したい</a></li> <li><a href="#特定の列行だけ取り出してから計算する">特定の列・行だけ取り出してから計算する</a></li> <li><a href="#describeメソッドで全体の雰囲気を掴む">describeメソッドで全体の雰囲気を掴む</a></li> </ul> </div> <div class="section"> <h3 id="列の平均と標準偏差を計算したい">列の平均と標準偏差を計算したい</h3> <p> とても簡単にできます。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd &gt;&gt;&gt; df = pd.DataFrame([[<span class="synConstant">1</span>,<span class="synConstant">2</span>,<span class="synConstant">3</span>,<span class="synConstant">4</span>,<span class="synConstant">5</span>,<span class="synConstant">6</span>], [<span class="synConstant">6</span>,<span class="synConstant">5</span>,<span class="synConstant">4</span>,<span class="synConstant">3</span>,<span class="synConstant">2</span>,<span class="synConstant">1</span>], [<span class="synConstant">0</span>,<span class="synConstant">1</span>,<span class="synConstant">2</span>,<span class="synConstant">3</span>,<span class="synConstant">4</span>,<span class="synConstant">5</span>], [<span class="synConstant">5</span>,<span class="synConstant">4</span>,<span class="synConstant">3</span>,<span class="synConstant">2</span>,<span class="synConstant">1</span>,<span class="synConstant">0</span>]], columns=[*<span class="synConstant">&quot;ABCDEF&quot;</span>]) &gt;&gt;&gt; df.mean() A <span class="synConstant">3.0</span> B <span class="synConstant">3.0</span> C <span class="synConstant">3.0</span> D <span class="synConstant">3.0</span> E <span class="synConstant">3.0</span> F <span class="synConstant">3.0</span> dtype: float64 &gt;&gt;&gt; df.std() A <span class="synConstant">2.943920</span> B <span class="synConstant">1.825742</span> C <span class="synConstant">0.816497</span> D <span class="synConstant">0.816497</span> E <span class="synConstant">1.825742</span> F <span class="synConstant">2.943920</span> dtype: float64 </pre><p> 何も考える必要はないのだった。</p><p> リファレンス:<br /> <a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.mean.html">pandas.DataFrame.mean &mdash; pandas 0.24.2 documentation</a><br /> <a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.std.html">pandas.DataFrame.std &mdash; pandas 0.24.2 documentation</a></p><p></p> </div> <div class="section"> <h3 id="行の平均と標準偏差を計算したい">行の平均と標準偏差を計算したい</h3> <p> 「転置しとけば?」という天の声が聞こえたのを無視してやります。</p><p> numpy配列のようにaxisを指定するだけなのでこれも簡単です。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd &gt;&gt;&gt; df = pd.DataFrame([[<span class="synConstant">1</span>,<span class="synConstant">2</span>,<span class="synConstant">3</span>,<span class="synConstant">4</span>,<span class="synConstant">5</span>,<span class="synConstant">6</span>], [<span class="synConstant">6</span>,<span class="synConstant">5</span>,<span class="synConstant">4</span>,<span class="synConstant">3</span>,<span class="synConstant">2</span>,<span class="synConstant">1</span>], [<span class="synConstant">0</span>,<span class="synConstant">1</span>,<span class="synConstant">2</span>,<span class="synConstant">3</span>,<span class="synConstant">4</span>,<span class="synConstant">5</span>], [<span class="synConstant">5</span>,<span class="synConstant">4</span>,<span class="synConstant">3</span>,<span class="synConstant">2</span>,<span class="synConstant">1</span>,<span class="synConstant">0</span>]], columns=[*<span class="synConstant">&quot;ABCDEF&quot;</span>]) &gt;&gt;&gt; df.mean(axis=<span class="synConstant">1</span>) <span class="synConstant">0</span> <span class="synConstant">3.5</span> <span class="synConstant">1</span> <span class="synConstant">3.5</span> <span class="synConstant">2</span> <span class="synConstant">2.5</span> <span class="synConstant">3</span> <span class="synConstant">2.5</span> dtype: float64 &gt;&gt;&gt; df.std(axis=<span class="synConstant">1</span>) <span class="synConstant">0</span> <span class="synConstant">1.870829</span> <span class="synConstant">1</span> <span class="synConstant">1.870829</span> <span class="synConstant">2</span> <span class="synConstant">1.870829</span> <span class="synConstant">3</span> <span class="synConstant">1.870829</span> dtype: float64 </pre><p> よくできてますね。</p> </div> <div class="section"> <h3 id="特定の列行だけ取り出してから計算する">特定の列・行だけ取り出してから計算する</h3> <p> 基本的なindexing操作と組み合わせて使うことで、特定の行・列だけに対して計算するということも可能です。</p><p> A, Bに対してのみ出力させたい場合。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; df[[<span class="synConstant">&quot;A&quot;</span>, <span class="synConstant">&quot;B&quot;</span>]].mean() A <span class="synConstant">3.0</span> B <span class="synConstant">3.0</span> dtype: float64 </pre> </div> <div class="section"> <h3 id="describeメソッドで全体の雰囲気を掴む">describeメソッドで全体の雰囲気を掴む</h3> <p> describeメソッドを使うと様々な統計量を勝手に出してくれます。</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;&gt; df.describe() <span class="synComment"># 列ごとに</span> A B C D E F count <span class="synConstant">4.00000</span> <span class="synConstant">4.000000</span> <span class="synConstant">4.000000</span> <span class="synConstant">4.000000</span> <span class="synConstant">4.000000</span> <span class="synConstant">4.00000</span> mean <span class="synConstant">3.00000</span> <span class="synConstant">3.000000</span> <span class="synConstant">3.000000</span> <span class="synConstant">3.000000</span> <span class="synConstant">3.000000</span> <span class="synConstant">3.00000</span> std <span class="synConstant">2.94392</span> <span class="synConstant">1.825742</span> <span class="synConstant">0.816497</span> <span class="synConstant">0.816497</span> <span class="synConstant">1.825742</span> <span class="synConstant">2.94392</span> <span class="synIdentifier">min</span> <span class="synConstant">0.00000</span> <span class="synConstant">1.000000</span> <span class="synConstant">2.000000</span> <span class="synConstant">2.000000</span> <span class="synConstant">1.000000</span> <span class="synConstant">0.00000</span> <span class="synConstant">25</span>% <span class="synConstant">0.75000</span> <span class="synConstant">1.750000</span> <span class="synConstant">2.750000</span> <span class="synConstant">2.750000</span> <span class="synConstant">1.750000</span> <span class="synConstant">0.75000</span> <span class="synConstant">50</span>% <span class="synConstant">3.00000</span> <span class="synConstant">3.000000</span> <span class="synConstant">3.000000</span> <span class="synConstant">3.000000</span> <span class="synConstant">3.000000</span> <span class="synConstant">3.00000</span> <span class="synConstant">75</span>% <span class="synConstant">5.25000</span> <span class="synConstant">4.250000</span> <span class="synConstant">3.250000</span> <span class="synConstant">3.250000</span> <span class="synConstant">4.250000</span> <span class="synConstant">5.25000</span> <span class="synIdentifier">max</span> <span class="synConstant">6.00000</span> <span class="synConstant">5.000000</span> <span class="synConstant">4.000000</span> <span class="synConstant">4.000000</span> <span class="synConstant">5.000000</span> <span class="synConstant">6.00000</span> &gt;&gt;&gt; df.T.describe() <span class="synComment"># describeで行ごとに処理したい場合は転置する</span> <span class="synConstant">0</span> <span class="synConstant">1</span> <span class="synConstant">2</span> <span class="synConstant">3</span> count <span class="synConstant">6.000000</span> <span class="synConstant">6.000000</span> <span class="synConstant">6.000000</span> <span class="synConstant">6.000000</span> mean <span class="synConstant">3.500000</span> <span class="synConstant">3.500000</span> <span class="synConstant">2.500000</span> <span class="synConstant">2.500000</span> std <span class="synConstant">1.870829</span> <span class="synConstant">1.870829</span> <span class="synConstant">1.870829</span> <span class="synConstant">1.870829</span> <span class="synIdentifier">min</span> <span class="synConstant">1.000000</span> <span class="synConstant">1.000000</span> <span class="synConstant">0.000000</span> <span class="synConstant">0.000000</span> <span class="synConstant">25</span>% <span class="synConstant">2.250000</span> <span class="synConstant">2.250000</span> <span class="synConstant">1.250000</span> <span class="synConstant">1.250000</span> <span class="synConstant">50</span>% <span class="synConstant">3.500000</span> <span class="synConstant">3.500000</span> <span class="synConstant">2.500000</span> <span class="synConstant">2.500000</span> <span class="synConstant">75</span>% <span class="synConstant">4.750000</span> <span class="synConstant">4.750000</span> <span class="synConstant">3.750000</span> <span class="synConstant">3.750000</span> <span class="synIdentifier">max</span> <span class="synConstant">6.000000</span> <span class="synConstant">6.000000</span> <span class="synConstant">5.000000</span> <span class="synConstant">5.000000</span> </pre><p> 参考:<br /> <a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.describe.html">pandas.DataFrame.describe &mdash; pandas 0.24.2 documentation</a><br /> <a href="https://note.nkmk.me/python-pandas-describe/">pandas&#x306E;describe&#x3067;&#x5404;&#x5217;&#x306E;&#x8981;&#x7D04;&#x7D71;&#x8A08;&#x91CF;&#xFF08;&#x5E73;&#x5747;&#x3001;&#x6A19;&#x6E96;&#x504F;&#x5DEE;&#x306A;&#x3069;&#xFF09;&#x3092;&#x53D6;&#x5F97; | note.nkmk.me</a></p> </div> hayataka2049 【python】クラスタリング結果を積み上げ棒グラフで可視化する hatenablog://entry/17391345971625758771 2018-03-15T05:35:55+09:00 2019-06-26T00:01:18+09:00 ラベル付きデータをクラスタリングすることがよくあります(そんな頻繁にあるか? まあ、クラスタリングの使い方次第でたまにはあるからこうして記事にしている訳ですが)。各クラスタの中身がどんなラベルで構成されているのか、知りたくなります。積み上げ棒グラフで出てくれると嬉しいですね(嬉しさがわからない方も読み進めて頂ければわかるので大丈夫)。pythonでの積み上げ棒グラフの描きをググると、matplotlibを駆使した怖い(大変そうな)描き方がいくらでも出てくるのですが、そんなことで苦労したくないので簡単なやり方でやります。 <div class="section"> <h3>はじめに</h3> <p> ラベル付きデータをクラスタリングすることがよくあります(そんな頻繁にあるか? まあ、クラスタリングの使い方次第でたまにはあるからこうして記事にしている訳ですが)。</p><p> 各クラスタの中身がどんなラベルで構成されているのか、知りたくなります。積み上げ棒グラフで出てくれると嬉しいですね(嬉しさがわからない方も読み進めて頂ければわかるので大丈夫)。</p><p> pythonでの積み上げ棒グラフの描きをググると、matplotlibを駆使した怖い(大変そうな)描き方がいくらでも出てくるのですが、そんなことで苦労したくないので簡単なやり方でやります。</p> </div> <div class="section"> <h3>やりかた</h3> <p> こちらを参考にしました。<br /> <a href="https://ja.stackoverflow.com/questions/33034/pandas%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%81%8B%E3%82%89%E7%A9%8D%E3%81%BF%E4%B8%8A%E3%81%92%E6%A3%92%E3%82%B0%E3%83%A9%E3%83%95%E3%82%92%E4%BD%9C%E3%82%8A%E3%81%9F%E3%81%84">python - pandas&#x306E;&#x30C7;&#x30FC;&#x30BF;&#x30D5;&#x30EC;&#x30FC;&#x30E0;&#x304B;&#x3089;&#x7A4D;&#x307F;&#x4E0A;&#x3052;&#x68D2;&#x30B0;&#x30E9;&#x30D5;&#x3092;&#x4F5C;&#x308A;&#x305F;&#x3044; - &#x30B9;&#x30BF;&#x30C3;&#x30AF;&#x30FB;&#x30AA;&#x30FC;&#x30D0;&#x30FC;&#x30D5;&#x30ED;&#x30FC;</a><br />  ぜんぶpandasの機能でできるらしいです。素敵。要するにクロス集計してplotしてやれば良い、ということのようです。</p> <ul> <li><a href="https://pandas.pydata.org/pandas-docs/stable/generated/pandas.crosstab.html">pandas.crosstab &mdash; pandas 0.23.4 documentation</a></li> <li><a href="https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.plot.html">pandas.DataFrame.plot &mdash; pandas 0.23.4 documentation</a></li> </ul> </div> <div class="section"> <h3>やってみた</h3> <p> irisとdigitsをクラスタリングし、上の方法を参考にグラフ化してみます。</p><p> ソースコード</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># coding: UTF-8</span> <span class="synPreProc">import</span> numpy <span class="synStatement">as</span> np <span class="synPreProc">import</span> pandas <span class="synStatement">as</span> pd <span class="synPreProc">from</span> sklearn.datasets <span class="synPreProc">import</span> load_digits, load_iris <span class="synPreProc">from</span> sklearn.cluster <span class="synPreProc">import</span> KMeans <span class="synPreProc">import</span> matplotlib.pyplot <span class="synStatement">as</span> plt <span class="synStatement">def</span> <span class="synIdentifier">visualize</span>(y_true, y_cl, y_names, filename=<span class="synConstant">&quot;result.png&quot;</span>): y_true = np.array([y_names[y] <span class="synStatement">for</span> y <span class="synStatement">in</span> y_true]) df = pd.crosstab(y_cl, y_true, rownames=[<span class="synConstant">&quot;cluster number&quot;</span>], colnames=[<span class="synConstant">&quot;true label&quot;</span>]) <span class="synIdentifier">print</span>(df) plt.figure() df.plot(kind=<span class="synConstant">'bar'</span>,stacked=<span class="synIdentifier">True</span>, legend=<span class="synIdentifier">False</span>) plt.legend(bbox_to_anchor=(<span class="synConstant">1.13</span>, <span class="synConstant">1</span>), loc=<span class="synConstant">&quot;upper right&quot;</span>) plt.savefig(filename) <span class="synStatement">def</span> <span class="synIdentifier">main</span>(): iris = load_iris() km = KMeans(n_clusters=<span class="synConstant">3</span>, n_init=<span class="synConstant">30</span>, max_iter=<span class="synConstant">1000</span>) cluster_labels = km.fit_predict(iris.data) <span class="synIdentifier">print</span>(<span class="synConstant">&quot;iris&quot;</span>) visualize(iris.target, cluster_labels, iris.target_names, filename=<span class="synConstant">&quot;iris.png&quot;</span>) digits = load_digits() km = KMeans(n_clusters=<span class="synConstant">10</span>, n_init=<span class="synConstant">30</span>, max_iter=<span class="synConstant">1000</span>) cluster_labels = km.fit_predict(digits.data) <span class="synIdentifier">print</span>(<span class="synConstant">&quot;digits&quot;</span>) visualize(digits.target, cluster_labels, digits.target_names, filename=<span class="synConstant">&quot;digits.png&quot;</span>) <span class="synStatement">if</span> __name__ == <span class="synConstant">&quot;__main__&quot;</span>: main() </pre><p> とりあえず、クロス集計した結果のDFをテキストで吐いてみたので、そっちから見せます。</p> <pre class="code" data-lang="" data-unlink>iris true label setosa versicolor virginica cluster number 0 50 0 0 1 0 48 14 2 0 2 36 digits true label 0 1 2 3 4 5 6 7 8 9 cluster number 0 177 0 1 0 0 0 1 0 0 0 1 0 24 148 0 0 0 0 0 3 0 2 0 0 3 7 10 0 0 177 5 8 3 1 0 0 0 166 2 0 0 0 0 4 0 1 13 155 0 2 0 0 2 6 5 0 1 0 2 0 136 0 0 4 5 6 0 2 0 0 0 1 177 0 2 0 7 0 0 2 12 0 41 0 0 51 140 8 0 100 8 7 2 0 3 2 101 1 9 0 54 2 0 3 0 0 0 6 20</pre><p> なるほど。まあ、なんとなくどんな状態になっているのかはこの表からもわかります。</p><p> そしてお待ちかねのグラフはこちら。<figure class="figure-image figure-image-fotolife" title="iris"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hayataka2049/20180315/20180315052841.png" alt="iris&#x306E;&#x7D50;&#x679C;" title="f:id:hayataka2049:20180315052841p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>iris</figcaption></figure><figure class="figure-image figure-image-fotolife" title="digits"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hayataka2049/20180315/20180315052849.png" alt="digits&#x306E;&#x7D50;&#x679C;" title="f:id:hayataka2049:20180315052849p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>digits</figcaption></figure> わかりやすいですね。この記事で言いたいことは、この絵を簡単に得られるpandasは便利、ということだけです。</p><p> 一応グラフの説明をすると、このグラフは各クラスタに割り振られたデータのラベルの件数を表しています。そして、たとえばirisのグラフからは、setosaは完全に一つのクラスタを形成していますが、versicolorとviriginicaは綺麗にクラスタには分かれず混ざる、ということがわかります。versicolorとviriginicaが似ている、というかベクトル空間上で近くにいる、という知見が得られる訳です。</p> </div> <div class="section"> <h3>まとめ</h3> <p> pandasは独自の世界観があって正直苦手なんですが、たまに便利に使えることがあるなぁと思いました(小並感)。</p> </div> hayataka2049