NumPy.add.atなどのユニバーサル関数+at

NumPyについて書くシリーズの続きです。

ユニバーサル関数(ufunc)とは、ベクトル化演算です。いくつもの要素がある中で、一つ一つ処理するよりも、一度に処理したほうが早いですよね。そういうことをやってくれる関数です。

たい焼きを焼くときに、一つ一つ焼いていると大変です。しかし、たい焼き屋さんでは、いくつものたい焼きの穴が開いている鉄板で一度にたくさんのたい焼きをバシッ!!と作りますよね。あんこを足すときも、一度にできて早いですよね。あれのイメージです。

で、今回は、特にそのユニバーサル関数を at と組み合わせた時の動作がちょっとわかりづらかったので書いておきます。

下記の公式サイトにある
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.at.html
例なのですが

import numpy as np

a = np.array([1, 2, 3, 4])
np.add.at(a, [0, 1], 1)
print(a)
#下記が出力されます。
array([2, 3, 3, 4])

これを例にとって説明するとadd.atの

・1番目の引数は処理する配列

・2番目の引数は処理したいインデックス

・3番目の引数は、addしたい数

です。

私はPHPとかJavaとかが長いので、こういう「1を加算する」的な処理はついついfor文とかでループで書いてしまいがちなのですが、速さが違うので、NumPyのユニバーサル関数を使いこなしていきたいと思います!!

Outlook メール送信時にSlackに投稿する

WordやExcel等の例に漏れず、Outlookもマクロが組めます。

メール送信時のアクションとして、SlackのIncoming Webhookを叩いてみます。

タスク管理などに応用できるかも?

Outlookでマクロを使うための下準備

マクロを組む準備と、マクロを実行できるように設定をいじります。 Outlookのメニューバーから操作します。

  1. ファイル > オプション > ユーザーリボン と選択し、開発 をONにする
  2. メニューバーに、開発タブが表示される
  3. 開発 > Visual Basic を開いて作成する

Webhookを利用してSlackに投稿する

この記事の例では、SlackのIncoming Webhookというインテグレーションを利用します。

Incoming Webhookの利用については、以下の記事に説明があります。

Slack Incoming Webhookの利用

マクロの作成

Incoming Webhookが発行する受信用URLにHTTPリクエストを送信し、Slackへの投稿を行うサンプルです。

開発 > Visual Basic > 画面左上のProject1以下を展開 > ThisOutlookSessionを開きます。

ThisOutlookSessionに以下を記述して保存します。

Outlookから送信したメールを、SlackにもPOSTします。

TargetURL = "https://hooks.slack.com/services/…"

12行目のTargetURLには、Incoming Webhookで生成したURLを指定します。

sendText = "payload={""text"":""件名: " & objMail.Subject & "\n本文: " & Left(objMail.Body, 200) & """}"

17行目のsendText部分が、実際にWebhookのURLに送信される内容です。メールの件名と本文をPOSTしています。

Left(objMail.Body, 200)

メールの引用などで本文が長すぎると投稿が大変なことになるため、sendText内の上記部分で、半角200文字分だけ投稿されるようにしています。

こんな具合に投稿されます

指定チャンネルへのPOST

デフォルトでは、マクロからPOSTした内容は、Incoming Webhookで設定してある送信先チャンネルに投稿されるようになっています。

sendTextの部分でchannelプロパティを指定することで、任意のpublicチャンネル、ユーザーのDMへ投稿することが可能です。

  • randomチャンネルへの投稿
sendText = "payload={""channel"":""#random"", ""text"":""件名: " & objMail.Subject & "\n本文: " & Left(objMail.Body, 200) & """}"
  • 特定ユーザーのDMへ投稿
sendText = "payload={""channel"":""XXXXXXXXX"", ""text"":""件名: " & objMail.Subject & "\n本文: " & Left(objMail.Body, 200) & """}"

XXXXXXXXXの箇所は、Slackのchannel/ユーザーの識別IDです。チャンネル名あるいはユーザー名を右クリックして取得します。

※右クリック > リンクをコピー > 以下のような形で取得できるリンクの、末尾部分がIDになります。

https://hogehoge.slack.com/team/XXXXXXXXX

投稿にメンションを含める

SlackのIncoming Webhooksでメンションを飛ばす方法を参考にする。

sendText内、textプロパティにて、以下の書式に則ってメンションを記述することができます。

記法メンション
<!here>@here
<!channel>@channel
<@user_id>@michael

記述例

sendText = "payload={""text"":""<!channel> 件名: " & objMail.Subject & "\n本文: " & Left(objMail.Body, 200) & """}"

マクロ作成後、実行できない(有効にならない)場合

マクロの実行時に警告が出て実行できないなどがあれば、署名の作成を行うと解決する場合があります。マクロのセキュリティ設定で、署名のないマクロをブロックするようになっていることが多いです。

最近では下記のファイルを直接実行してデジタル署名を作成するらしいですが、ちょっと怖いですよね。

※ 署名を作らなくてもマクロを有効にできます。何か起きても責任は取れません。

C:\Program Files\Microsoft Office\root\Office16\SELFCERT.EXE

署名の作成を行ったのにまだマクロが動いてくれない場合、一度警告を出させ、明示的に実行を許可してやるとうまくいくケースがあります。
署名を作成しない場合でも、この手順は有効みたいです(動いた例あり)。

  1. (Outlookのメニューバー)開発 > マクロのセキュリティ を開く
  2. すべてのマクロに対して警告を表示する にチェックして保存
  3. Outlookを再起動
  4. マクロの実行について警告のポップアップが表示される
  5. 実行を許可し、マクロを有効化
  6. マクロの動作をテストし、動いたらガッツポーズ

※ 署名を付けてマクロを作成した場合は、ここで署名単位で実行を許可することができます。後々マクロの変更とか作成とかした際に実行許可の手間が省けるとかそういう話です。

参考

Slack Incoming Webhookの利用

SlackではWebhookが利用できます。

Incoming Webhookは受信用のWebhookです。
送信用Webhookも利用できますが、まだ使ったことがないのでここでは触れません。

連携の登録

Slackにカスタムインテグレーションを追加します。

普段Slackのデスクトップアプリを利用している場合は、予めブラウザ上でサインインしておくとスムーズです。

  1. SlackのAppディレクトリを開き、Incoming Webhookを検索してアプリの個別ページを開く
  2. [設定を追加]をクリックし、新しいwebhookを登録する
    • ※ 設定1つにつきSlackの連携枠を1つ消費するので、用途別に設定を複数作るような使い方は無料プランでは厳しい
  3. チャンネルあるいはDMへincoming-webhookを追加する(設定の追加時のみ)
    1. チャンネルへの投稿: 投稿先チャンネル(あるいは自分へのDM)を選択
    2. [Incoming Webhookを追加]をクリックし、当該チャンネルにincoming-webhookが追加されたのを確認

設定の変更

Incoming Webhookの設定を変更します。

  1. チャンネルへの投稿: 投稿先チャンネル
  2. Webhook URL: Webhook利用時に使うURL(このURLにJSONペイロードを送信してアクションを起こす)
  3. 説明ラベル: インテグレーションの設定についての説明文(任意)
  4. 名前をカスタマイズ: Slack投稿時の名称が変えられる(デフォルトはincoming-webhook)
  5. アイコンをカスタマイズする: Slack投稿時のアイコンが変えられる(絵文字もアイコンとして設定できるが、アイコンとして表示される画像が絵文字と異なる場合がある)
  6. メッセージをプレビューする: 現在の名前、アイコンだとどういった表示になるかのプレビュー(アイコンに絵文字を選択した場合、画面を再読込するとアイコン画像が変化する場合がある)
  7. 設定を保存して終了

使ってみる

Webhook URLの取得

ミスがないよう、コピーして使う。
1つのWebhookURLを使い回している場合、再生成すると全連携が機能停止するので気を付ける。

  1. Incoming Webhookのページを開き、使用したいインテグレーション設定の編集ボタンを押す
  2. Webhook URLをコピーする

Webhook URLを叩く

PHP

Python

  • 調整中。

VBA

参考

NumPy where どの列を調べるか指定する

前回に引き続き、NumPyのちょっと便利な使い方です。

Numpy.where

は配列の中の要素を調べるための有名な関数で、皆さん使ってるかと思います。

標準的な使い方は下記の通りです。

import numpy as np

pieces = np.array([
[1, 0, 0],
[0, 0, 1],
[0, 0, 0]
])

array = np.array([1,0,0])

ndarray = np.where(array == 1, True, False)

print(ndarray)

#下記が出力されます。
[ True False False]

下記のサイトさんなどにも詳しいです。

NumPyで条件に応じた処理を行うwhereの使い方

他のサイトさんであまり紹介されていなくって、今回書いておきたいwhereの使い方が、2次元配列をwhereで調べる時に、列を指定する、というやり方です。

import numpy as np

pieces = np.array([
[1, 0, 0],
[0, 0, 1],
[0, 0, 0]
])

ndarray = np.where(pieces == 1, True, False)[1]

print(ndarray)

#下記が出力されます。
[False False True]

上記のように、whereの後にインデックス[1]をつけると、piecesの2列目(0からカウントなので、1は2番目)が1かどうかを判定して、True, Falseを返してくれてます。

Numpy 2つの配列を比較して重複していない要素を配列にする

前回に引き続き、NumPyについてのちょっと便利な関数を紹介してます。

setdiff1d()

という関数があります。

まずはサンプルです。

import numpy as np

array1 = np.arange(4)
print(array1)

array2 = np.arange(3)
print(array2)

print(np.setdiff1d(array1, array2))

#次のように出力されます
[0 1 2 3]
[0 1 2]
[3]
[0 1 2 3]


[0 1 2]

の差を教えてくれてますね。

ちなみに逆にすると、空の配列が出力されます。

import numpy as np

array1 = np.arange(4)
print(array1)

array2 = np.arange(3)
print(array2)

print(np.setdiff1d(array2, array1))

#次が出力されます。

[0 1 2 3]
[0 1 2]
[]

ちなみに、setdiff1dがあるなら、 setdiff2dがありそうですが、ありません!!

下記のようなやり方でできるようです。(確認はしていません)
https://stackoverflow.com/questions/8317022/get-intersecting-rows-across-two-2d-numpy-arrays