asken テックブログ

askenエンジニアが日々どんなことに取り組み、どんな「学び」を得ているか、よもやま話も織り交ぜつつ綴っていきます。 皆さまにも一緒に学びを楽しんでいただけたら幸いです!

あすけんSlackの人気絵文字ランキング

はじめまして!
askenのユウマと申します😊

shoku-pan🍞という名前でTwitterをやっています。
askenでは、MLエンジニアとして働いてます。
主に、画像処理や自然言語処理、データサイエンス周りを担当しています。
また、業務効率化のためのツールの作成や、ナレッジ共有のための社内勉強会を開いたりもしてます。
社外では、kaggleやatmaCupに参加したり、データサイエンティストの方達ともくもく作業したりと、ゆるゆると活動しています。

さて、先日以下のTweetが弊社のエンジニアの間で話題になりました。

最近よく目にする(気がする)この動く棒グラフは、「bar chart race」と呼ばれるものらしいですね。
Slack APIで、社内Slackの絵文字データを集計し、データを可視化するツールを使えばできるようです!
僕自身、Slack APIを使った経験はあまりなく、「Slackのデータを色々と分析できたら面白いだろうな」と思っていました。

弊社askenのSlackでもやってみたので、この記事で紹介します😊

目次

  • はじめに
  • 目次
  • 全体の流れ
  • セットアップ
    • Slack Appの作成
  • 実装
  • Bar chart raceの表示
  • 🎉結果発表🎉
  • まとめ
  • 参考資料

全体の流れ

まず、全体の流れは以下になります。

  • セットアップ
    • Slack Appの作成
  • 実装
    • Slackからメッセージ履歴を取得
    • 絵文字データを抽出・集計
    • csvファイルに出力
  • 可視化
    • Flourishにcsvファイルをインポート
    • bar chart raceの表示

セットアップ

Slack Appの作成

まず、Slackからデータを取得するために、Slack Appを作成します。 Slack Appの作成方法は、こちらの記事
Slack API | Web API から Slack App 経由で チャンネル履歴を取得する
を参考にしました。
ここで、Slack APIにどこまで権限を与えるか(スコープ)を決める必要があるのですが、今回は

  • channels:history
  • reactions:read

を指定しました。
※OAuth & Permissions > Scopes > User Token Scopes で設定できます。
スコープを指定してSlack APPを作成し、Slackのワークスペースにインストールできれば、いよいよ実装です!

実装

今回、言語はPython、環境はGoogle Colaboratoryを使用しました。
それでは、まずは設定です。

# Settings
TOKEN = '[token ID]'
CHANNEL = '[channel ID]'
NUMDAYS = 365 # データを取得する日数

ここで、[token ID]には
OAuth & Permissions > OAuth Tokens for Your Workspace > User OAuth Token
に記載されている文字列を指定します。
[channel ID]の確認方法は以下が参考になります。
Slack — APIに使う「チャンネルID」を取得する方法
※なお、これらは重要な情報なので、取り扱いに注意して下さい

NUMDAYSには、過去何日分のデータを取得するかを指定しています。
今回は1年分となる365日を指定しました。
※この値が大きいほど、データの取得には時間がかかります。

あらかじめ、必要なライブラリもインポートしておきます。

# Import libraries
import pandas as pd
import requests
import datetime

次に関数を定義します。

# Functions
def get_conversations_history(oldest_date, latest_date):
    """
    メッセージ履歴を取得する
    """
    url = "https://slack.com/api/conversations.history"
    headers = {"Authorization": "Bearer "+TOKEN}
    params = {
    "channel": CHANNEL,
    "limit": 1000,
    "oldest": oldest_date,
    "latest": latest_date,
    }
    response = requests.get(url, headers=headers, params=params)
    return response.json()
def count_emoji(conversations_history, df, date):
    """
    メッセージ履歴から絵文字をカウントする
    """
    for i in conversations_history['messages']:
        if 'ts' in i and 'reactions' in i:
            ts = i['ts']
            ts = datetime.datetime.fromtimestamp(int(ts.split('.')[0])) # unix時刻から標準時刻へ変換
            ts = ts.date() # 日付部分のみ取得
            reactions = i['reactions']
            for reaction in reactions:
                reaction_name = reaction['name']
                reaction_count = reaction['count']
                if reaction_name not in df.index:
                    df.loc[reaction_name] = 0
                df[date][df.index==reaction_name] += reaction_count

メインの処理は以下になります。

# Main
# 絵文字データをdataframeに格納
df=pd.DataFrame()
today = datetime.datetime.today()
# 今日の日付からNUMDAYS日前までのデータを取得。
# reversedで、日付の古い順に並び替え
for index, i in enumerate(reversed(range(0, NUMDAYS))):
    date_new = today - datetime.timedelta(days=i)
    date_old = today - datetime.timedelta(days=i+1)
    # Slack APIの時刻parameterはunix timeなので変換
    date_new_unix = date_new.timestamp()
    date_old_unix = date_old.timestamp()
    if index == 0:
        # df[date]に各絵文字の集計結果を格納する。カウント初日は0
        df[date_new.date()] = 0
    else:
        # df[date]に各絵文字の集計結果を格納する。前日の集計結果に足していく。
        df[date_new.date()] = df[date_old.date()]
        conversations_history = get_conversations_history(oldest_date=date_old_unix, latest_date=date_new_unix)
        if conversations_history['ok']: # responseが正しく返ってきた場合のみ処理実行
            count_emoji(conversations_history, df, date_new.date())
    
df # 結果確認

実行すると、以下のようなDataframeが出力されるはずです。
Slackの絵文字データがちゃんと集計されていますね!

f:id:techaskeninc:20210826174543p:plain

1日毎だとデータ量(カラム)が多すぎるので、1週間ごとに集計し直しました。
※カラムが多すぎると、この後Flourishにインポートしたときに全てのデータを表示することができませんでした。。

# Modify dataframe
df_result = df.copy()
df_weekly = pd.DataFrame()
for i in range(2, len(df_result.columns)):
    if i % 7 == 0:
        df_weekly[df_result.columns[i]] = df_result[df_result.columns[i]]
df_weekly

実行すると、以下のように出力されます。
今度は絵文字データが1週間単位(7日ごと)で集計されていますね!

f:id:techaskeninc:20210826174702p:plain

最後に、Dataframeをcsvファイルに出力しましょう。

# Output
df_weekly.to_csv('emoji_ranking_weekly.csv')

Bar chart raceの表示

ここまでで、Slackのデータを収集して絵文字データを集計し、結果をcsvファイルに出力するところまでできました。
では、このデータを使ってBar chart raceを表示してみましょう。
今回、Bar chart raceを表示するにあたっては、Flourishというサービスを使用しました。
こちらにアクセスしてください。
チュートリアルに従ってcsvファイルをupすれば、bar chart raceが表示されるハズです😉

🎉結果発表🎉

それでは、askenのSlackチャンネルの絵文字ランキングを発表します!
今回集計したデータは以下になります。

  • 全ての絵文字を集計(デフォルト絵文字およびカスタム絵文字)
  • generalチャンネル
  • リアクションとして使用された絵文字に限る(本文中で使用された絵文字は対象外)
  • 集計の期間は直近までの1年間
  • 上位15位を表示

直近1年間での集計の最終的なランキングは以下になりました🎉

順位 絵文字 絵文字名
🥇 tada
🥈 bows
🥉 done
4位 +1
5位 ok_hand
6位 ultra_fast_parrot
7位 asken2
8位 miki
9位 heart
10位 odaizini
11位 man-gesturing-ok
12位 woman-bowing
13位 nyan_parrot
14位 muscle
15位 sob

1位は🎉でした!新しいサービスのリリースやメディアでの紹介、また新入社員の紹介など、おめでたいことやテンションのあがる投稿に対するリアクションとして多く使われていました。
2位のは、「ありがとう」と感謝の気持ちをつたえる際に、3位のは依頼された作業を完了したときに使用されているようです。
また、7位には弊社サービス「あすけん」のロゴが、8位にはそのキャラクターの未来さんがランクインしていました。
これら2つはカスタム絵文字で、askenらしさがよく出た結果となりました😊

まとめ

いかがでしたか?

今回は、弊社askenのSlackの絵文字データを集計して、bar chart raceを表示してみました。
Slack APIを使用して、Pythonでデータを抽出・集計し、Flourishというサービスを使用することでつくることができます。

みなさんの会社でもやってみてはいかがでしょうか?
盛り上がること間違いなしだと思います!
ぜひ、皆さんの会社の絵文字ランキングも教えて下さいね

参考資料