今日覚えたNumPyのテクニック

今日覚えたNumPyのテクニックを紹介します。

numpy.stack で2次元配列を繋げて3次元配列を作る

1次元配列を繋げて2次元配列を作りたいような場合には numpy.vstacknumpy.hstack という関数があります。

a = numpy.array([1, 2, 3, 4])
b = numpy.array([2, 4, 6, 8])
c = numpy.array([3, 6, 9, 12])
numpy.vstack([a, b, c])

# array([[ 1,  2,  3,  4],
#        [ 2,  4,  6,  8],
#        [ 3,  6,  9, 12]])

2次元配列を繋げて3次元配列を作りたいような場合にはどのようにすればよいか知らなかったのですが,numpy.stack という関数があることを知りました。

a = numpy.array([[1, 2, 3], [4, 5, 6]])
b = numpy.array([[2, 4, 6], [8, 10, 12]])
c = numpy.array([[3, 6, 9], [12, 15, 18]])
numpy.stack([a, b, c])

# array([[[ 1,  2,  3],
#         [ 4,  5,  6]],
#        [[ 2,  4,  6],
#         [ 8, 10, 12]],
#        [[ 3,  6,  9],
#         [12, 15, 18]]])

条件が3つ以上ある場合の条件演算子を integer array indexing で実現する

条件演算子 x ? a : b のようなことを配列のすべての要素に対してやりたい場合には numpy.where を使うことができます。

x = numpy.array([0, 1, 0, 1])
a = numpy.array([1, 2, 3, 4])
b = numpy.array([5, 6, 7, 8])
numpy.where(x, a, b)

# array([5, 2, 7, 4])

条件が3つ以上ある場合にどうすればよいか知らなかったので,いろいろ考えました。最初に思いつくのは numpy.where をネストして無理やり実現する方法です。

x = numpy.array([0, 1, 2, 1])
a = numpy.array([1, 2, 3, 4])
b = numpy.array([5, 6, 7, 8])
c = numpy.array([9, 10, 11, 12])
numpy.where(x == 0, a, numpy.where(x == 1, b, c))

# array([ 1,  6, 11,  8])

この方法では場合分けの個数が変化する場合に対応できなくなってしまうので不便です。別の方法として NumPy の indexing を使う方法を教えてもらいました。

x = numpy.array([0, 1, 2, 1])
a = numpy.array([1, 2, 3, 4])
b = numpy.array([5, 6, 7, 8])
c = numpy.array([9, 10, 11, 12])
u = numpy.stack([a, b, c])

# array([[ 1,  2,  3,  4],
#        [ 5,  6,  7,  8],
#        [ 9, 10, 11, 12]])

u[x, numpy.arange(x.shape[0])]

# array([ 1,  6, 11,  8])

列方向のインデックスとして numpy.arange を渡してやるのが重要で,u[x, :] ではうまくいきませんでした。

もっと良い方法をご存じの方はご連絡下さい。

ISUCON7の予選を学生枠で通過しました

ISUCON7の予選に @brook_bach さん,@mayoko_ さんと「座るだけのコンテストってな〜んだ?」で参加しました。

@brook_bach さんの記事

brookbach.com

@mayoko_ さんの記事

mayokoex.hatenablog.com

チーム結成の経緯

続きを読む

pyenv+Minicondaからdirenvに乗り換える

背景

pyenvを使っていた理由

Minicondaを使っていた理由

  • NumPyやSciPyをバイナリ形式でダウンロードしたかったから
    • Wheel環境が整備されていなかった時代はプロジェクト用のvirtualenvを作って pip install scipy をする毎にNumPyやSciPyのコンパイルのために手が止まってしまっていた

乗り換えようと思った理由

  • Python 2.6を使わなければいけないことが最近ではほとんど無くなったから(homebrewでインストールできるpython2.7とpython3で十分)
  • Wheel環境が整備されてきたのでpipでもバイナリ形式でダウンロードできるから

乗り換え先として試してみたもの

pyenv + pyenv-virtualenv

  • pyenvは残したままでMinicondaだけ捨てる方法
  • pyenv local を使うことで,ディレクトリを移動したときにvirtualenv環境を自動的に変更できる
  • 試してみると,なぜかシェルの動きがもっさりしてしまった(Enterキーを連打してみると分かりやすい。原因不明)
  • プロンプトに出てくるvirtualenv名を消す方法が分からないVIRTUAL_ENV_DISABLE_PROMPT を定義すればいいだけだった…

direnv

  • pyenvもMinicondaも捨てる方法
  • プロンプトに出てくるvirtualenv名を消すためには,source bin/activate するときに VIRTUAL_ENV_DISABLE_PROMPT という環境変数に空文字以外の値を入れておけばよい
  • pip install したときに /usr/local/bin が汚染されるのが怖すぎるので,デフォルトでvirtualenvを有効にするために以下の設定を .zshrc に書いている
if [[ -d "$HOME/.virtualenvs/default" ]]; then
  VIRTUAL_ENV_DISABLE_PROMPT=true source $HOME/.virtualenvs/default/bin/activate
fi
  • ディレクトリ移動時のvirtualenv環境を自動的に変更するには,以下の設定を .envrc に書いておけばよい
source $HOME/.virtualenvs/rime-python2/bin/activate