RareJob Tech Blog

レアジョブテクノロジーズのエンジニア・デザイナーによる技術ブログです

任意のサイトにあるaタグを別タブで開く

こんにちは。サービス開発チームのすずきです。

早速ですが、皆さんは外部リンクを別タブで開きたい派ですか?私は開きたい派です。 リンクを別タブで開くためにcommandを押しながらリンクをクリックするのですが、 毎回commandキーを押しながらクリックするのは少し手間です。 commandキーを押し忘れたら画面遷移してしまい、わざわざブラウザバックしなければいけません。

そこでChrome拡張機能であるScriptAutoRunnerを利用して、aタグのtarget属性に_blankを付与するようにしました。

github.com

利用方法は開発者のGithubに譲りますが、 以下のようにjsを記述することで、外部リンクを別タブで開くようにしました。

var anchors = document.getElementsByTagName('a');
for (var i = 0; i < anchors.length; i++) {
    var anchor = document.createElement('a');
    anchor.href = anchors[i].href;
    if (location.hostname !== anchor.hostname
        && anchor.href !== 'javascript:void(0);') {
        anchors[i].target = "_blank";
    }
}

では!

Airを使ったGo環境でのホットリロード

こんにちは。

つい先日誕生日だったのですが、昨今のアレコレのせいで独り寂しくお祝いしました。
アレコレが無ければきっと盛大にお祝いして貰えたはずだったのですが……
去年も一昨年もその前も独りでお祝いしたかもしれませんが、可能性は0では無いです。
サプライズパーティの準備をしていた方、大変申し訳ありません。
尚、私のカバンにはまだ若干の余裕があることだけはお伝えしておきます。

ホットリロード is 何?(実はライブリロード)

簡単にいうと「変更をすぐに反映してテストを行いやすくする機構」です。
修正がリアルタイムに反映されるためデバッグなどの作業が効率的に行えます。

実はホットリロードと言いつつ今回の話はホットリロードでは無いです。
何言うてるねんと言われそうですがGoは変更箇所の適用のため全体を読み直す為
「ホットリロード」ではなく「ライブリロード」になります。

  • 変更箇所だけ読み込んで反映するのがホットリロード
  • 変更箇所含めて全て読み込んで反映するのがライブリロード

と言うことだけ覚えておけば大丈夫です。
でも皆さんホットリロードと言ってる気がするのでどっちでもいい気がします。

伝わればいいのだ伝われば。

Go環境のホットリロードはRealizeが一番有名ですが、
現在ほぼ開発が止まっており、最新のmodulesを使う環境下ではエラーが出るなどから
代替を探して見つけたのがAirです。

とりあえずデフォルトで試す

何はともあれインストール

$ curl -fLo air https://git.io/darwin_air
$ chmod +x air
$ mv air /usr/local/bin 

Downloadしたairに実行権限をつけてパスが通っているところに移動させています。

次にテスト実行用の雑なsampleを用意

package main

import "fmt"

func main() {
    fmt.Println("Hello world!")
}

対象と同じディレクトリでAirを起動 f:id:dedekopon:20200626120731g:plain

Airの監視対象のファイルを修正する

package main

import "fmt"

func main() {
    fmt.Println("Hello world!")
    fmt.Println("Live reload!")
}

変更が反映され自動でリビルドされる f:id:dedekopon:20200626120739g:plain

まとめ

とりあえず動作確認しながらの開発には非常に便利そう。
実際はコンフィグを設定したりdocker上で動かしたり等もう一手間必要になりそうです。
コンフィグはexampleがあるのでそちらを参考に設定してみてください。

docker版 redash を最新版 v9 (ベータ版) へ upgrade する

redash の version 9 のベータ版が公開されました。

変更点がかなりあるので Changelog を見るだけでも面白いです。

V9 changelog (in master) by arikfr · Pull Request #4967 · getredash/redash · GitHub

個人的に興味深かった点が以下の 4つ です。

  • frontend は 100% React へ。( Angular、いままでありがとう!)
  • backend の job実行は Celery から RQ へ。
  • backend が Python 2 から 完全に Python 3へ。
  • data source に Amazon CloudWatch, Amazon CloudWatch Logs Insights が追加された。

と、今回の redash は frontend も backend も完全に刷新されており、今まであったメジャーアップデートの中でも一番のターニングポイントだと感じてます。

なにはともあれ version up

レアジョブでは redash が version 3.0 の時から使っており、定期的に version up をしていたのですが、1年半ほど前にversion 6 に上げてからは滞っておりました。

我々としては Amazon CloudWatch の連携が魅力に感じました。まずはベータ版というステータスなので社内の検証環境の redash を version upすることにしました。

redash は メジャー version up をすると redash 自体のデータを格納している postgres のスキーマ構造が変わることがよくあります。

version up するには redash で用意している migration tool を実行する必要があります。 ただし注意する必要があるのが

If you are currently running an instance of Redash prior to V7, do not upgrade directly to V8. Upgrade semantically to V7 first.

とあるように、 version が 7より下の場合は、まず先に version 7 へするようにと明記されています。 公式が提供している docker image を使いながら docker-compose.yml で定義する利用する docker image の version を一つづつあげていきます。

version 毎の docker image は以下公式ドキュメントをご覧ください。 https://redash.io/help/open-source/admin-guide/how-to-upgrade

例えば、version 6 から、version 7にあげる際は docker-compose.yml を以下のようにします。

before

services:
  server:
    image: redash/redash:6.0.0.b8537

after

services:
  server:
    image: redash/redash:7.0.0.b18042

その後

docker-compose run --rm server manage db upgrade

を行うと、server コンテナで migration tool が稼働し、redash の postgres に対しスキーマを変更しに行きます。 エラーが出なかったら

docker-compose up -d

で redash を起動してください。 login すると redash の version をブラウザ越しに確認することができます。 期待通りの version になっていることと、動作確認を行い問題なければ、先ほど行ったように docker-compose.yml で指定するイメージの version を上げて同様の作業を繰り返していきます。

version 9の起動

migration は成功しましたが、起動に失敗する事象に陥りました。

なぜ起動に失敗するのか原因を書く前に、 redash の構成をお話しする必要があると思います。 redash は 1つのコンテナイメージを使い複数コンテナを立ち上げ、それを相互に連携しあう事で動くようになっております。 https://github.com/getredash/redash/blob/master/bin/docker-entrypoint に定義してある server、scheduler、worker は最低限必要であり、 以下のように利用するコンテナイメージと、起動コマンドを定義して各コンテナを立ち上げる必要があります。

services:
  server:
    image: redash/redash:9.0.0-beta.b42121
    command: server
   (略)

  scheduler:
    image: redash/redash:9.0.0-beta.b42121
    command: scheduler
   (略)

  worker:
    image: redash/redash:9.0.0-beta.b42121
    command: worker
   (略)

この仕組み自体は以前と変わらないのですが今回、backend の仕組みが変わったことで、コンテナ を動かす上で必須となる環境変数が変わったことが原因のようです。

各コンテナに対して環境変数を書いていくと多くの場合冗長になってしまうので、公式の docker-compose.yml にある x-redash-environment のように環境変数の設定は1箇所にまとめ、各コンテナはそれを読み込むような作りにすると環境変数の漏れを防ぐことができるかもしれせん。

https://github.com/getredash/redash/blob/master/docker-compose.yml#L11

必要な環境変数が受け渡れば問題なく起動できます。

v9 を使うにあたってベンチマークスコアなどは取っておりませんが frontend も backend も生まれ変わったことで、レスポンスは体感で速くなったと感じています。

新しく追加された機能などについてはまた別の機会でお話しできればと思いますが、今回は docker版 redash を最新版へ upgrade する方法について記載させていただきました。

もちろん、今回はベータ版ですがGA になった場合は GA に update する予定です。

以上です。

Nuxt.jsプロジェクトにStorybookを導入する

こんにちは。APP・UXチームの大谷です。約1年ぶりくらいの投稿です。

最近は家にいることが多いので、ちょっと時間がかかる料理でもしてみよう。。
と餃子を皮から作ったりしています。餃子の皮を作る時は、お湯より水を使って練った方がモチモチ感がでて美味しいです。自分の好みにあった配合と焼き方を研究していきたい。

さて、今回は表題の通りNuxt.jsプロジェクトにStorybookを導入する方法について書いていきたいと思います。

Storybookとは?

StorybookとはUIコンポーネントをカタログのように一覧表示できたり、振る舞いをテストできるオープンソースのツールです。

storybook.js.org

なぜやるか?

新しく始まったプロジェクトをきっかけに、コンポーネントの管理方法やデザイナーとの連携について改めて整理してみようということでStorybookの導入が検討されました。

デザインチーム/フロントエンドチームで事前に用途についても協議してみました。

  • デザインチーム
    • コンポーネントのチェック(どんな種類/どんな挙動か)
    • スタイルガイドの管理
  • フロントエンドチーム
    • コンポーネントのチェック(どんな種類/どんな挙動か)
    • デザインチームへの共有

両チームとも基本的にコンポーネントの管理/共有に使いたい(ボタンやフォーム単位のパーツについて)という意見だったので、ページ全体など大きい単位での表示テストの用途には使わず、まずは小さい単位でのコンポーネントの管理/共有・スタイルガイドとして活用していこうという内容で認識を合わせました。

さっそくStorybookを導入してみる

まずはNuxtのサンプルプロジェクトを作成します。

% yarn create nuxt-app sample-project

作成したプロジェクト内でstorybookを導入していきます。

yarn add -D @storybook/cli
yarn sb init --type vue

yarn storybook

f:id:kinokonotani5656:20200611100741p:plain
storybook initial

storybook/cliは現在のlatest版(5.3.19)を使っています。
無事Storybookが立ち上がりましたが、Nuxtアプリケーションの本体を立ち上げようとしたらエラーが発生してしまいました。

yarn run dev
Type checking in progress...
 ERROR  Failed to compile with 39 errors
* core-js/modules/es6.array.from in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
 .............
To install them, you can run: npm install --save core-js/modules/es6.array.find core-js/modules/es6.array.from core-js/modules/es6.array.iterator core-js/modules/es6.date.to-string core-js/modules/es6.function.name core-js/modules/es6.object.assign  .............

core-jsでめちゃめちゃ怒られます。 Storybookを導入した時にbabelとcore-jsのバージョンで依存関係の問題が発生してしまうようです。解消するためにここでは明示的にcore-jsの2系を指定してインストールし直しました。

yarn add core-js@2

あとはstoriesファイルと設定を追加していきます。 今回はpropsやdescriptionを作るためのaddonも追加してみました。

yarn add -D @storybook/addon-knobs
yarn add -D storybook-addon-vue-info

addon有効にする設定を追加します。

// .storybook/addons.js
import 'storybook-addon-vue-info/lib/register';
import '@storybook/addon-knobs/register';

configファイルを追加します。

// .storybook/config.js
import { configure, addDecorator } from '@storybook/vue';
import { withKnobs } from "@storybook/addon-knobs";
import { withInfo } from 'storybook-addon-vue-info'

// xxx.stories.jsに対してaddonを反映
addDecorator(withInfo)
addDecorator(withKnobs);

// どのファイルを見るか設定する。今回は../components下のstoriesファイルを対象にする
configure(require.context('../components', true, /\.stories\.(js|ts)$/), module);

storiesファイルを作成。

import { storiesOf } from '@storybook/vue'
import { text, select } from '@storybook/addon-knobs'
// サンプルで作成したコンポーネント
import Button from '@/components/atoms/button/index.vue'

const stories = storiesOf('Buttons', module)

stories.add(
  'button sample story',
  () => {
    return {
      // 対象のコンポーネント設定
      components: { Button },
      props: {
        colorStyle: {
          type: String,
          default: select('colorType', ['green', 'orange'])
        },
        value: { type: String, default: text('default', 'sample') }
      },
    // 描画する内容を設定
      template: `<Button :value=value :colorStyle=colorStyle />`
    }
  },
  { info: true }
)

Buttonコンポーネントの表示を確認できるようになります。

f:id:kinokonotani5656:20200611100837p:plain

GitLab Pagesで公開

毎回環境を立ち上げなくてもいいようにGitLab Pagesで公開するようにしました。 masterにマージされたタイミングでGitLab Pagesを更新するようにしたgitlab-ci.ymlファイルの設定がこちらです。

image: node:latest

cache:
  paths:
  - node_modules/

pages:
  stage: deploy
  tags:
    - sample_runner
  only:
    - master
  before_script:
    - 'yarn install'
  script:
    - 'yarn build-storybook'
    - 'cp -pr storybook-static ./public'
  artifacts:
    paths:
      - public

最後に

今回は記載していませんが、Jestと連携してstoriesファイルのスナップショットテストをすることもできるようです。コンポーネントの管理/共有をするために便利なStorybookですが、更新せずに古くなってしまっては意味がないのでスナップショットテストと連携するなど必ず更新する仕組みをつくっていくことも課題になります。

実運用はまだはじまっていませんが、デザイナーとエンジニアお互いにとって幸せな開発環境にできれば良いなと思います!

デザインセンスとは?


どうも!お久しぶりです!デザイナーの渡辺です!
リモート勤務になって早2ヶ月になりました。
毎日ストレッチをしていたら、だいぶ体が柔らかくなってきました(*´∀`)

さて、今回は【デザインセンス】についてお話していこうと思います。
特に自分のことを【デザインセンスがない】と思っている方に見ていってほしいです!

最初に感じた疑問

私はデザイナーになってから、デザインセンスって一体なんだろう?と
考えるタイミングが何度かありました。

最初は新卒の時です。

Aさん:この企画のバナー作って!俺はデザインセンスないから見た目は任せる!
私:(私にデザインセンスってあるのか?)

単純にデザイナーだからデザインセンスを持っていると
思われていることに疑問を感じました。

私:私ってデザインセンスあるんですか?

先輩:ないだろ
私:わーバッサリー(棒)

そりゃもうバッサリでした笑

その後も事あるごとに、デザイナーではない方から
「自分にはデザインセンスがないのであとよろしく!」と言われることが多々ありました。
これはデザイナーのあるあるなんじゃないですかね?笑

デザインに必要なもの

そもそもデザインするのに何が必要なのか?
正直、なにもいらないと思ってます。
デザインしたければ、好きなようにデザインすればいいのです!

ただ、そのデザインを
【多くの人が良いと感じる】ものにするには

【知識】と【経験】
この2つが必要だと思ってます。

【知識】

  • 配色:色によって与える影響はなにか?
  • 配置:コンテンツの置く場所によって与える影響はなにか?
  • ボタンは押しやすいか?欲しい情報は得られるか?などを考えられるUIの概念
  • 与えたものによってどのような体験をするか、してほしいかを考えられるUXの概念

【経験】

  • 数多くの物を作ったり、目にしたことがあるか
  • 作ったものが成功したか
  • 作ったものが失敗したか
  • 失敗から成功に繋げられたか

など、挙げたらまだまだありますが
このような【知識】と【経験】を蓄積することにより
【多くの人が良いと感じる】ものを
作り出すことが、出来るのではないかと思います。

デザインセンスとは

では、デザインセンスとはなんなのか?

それは【知識】と【経験】を蓄積し、磨き上げた
自身のデザインスキルのことを言うのではないでしょうか?

蓄積することなく始めから持っているとすれば
それは才能です。

センスがあると才能があるは別物です。


【デザインセンスがない】というのは
デザインの【知識】と【経験】がないと言う意味なので、当たり前ですよね。
むしろ、初めからデザインセンスがある人のほうが希少です。
【知識】と【経験】がなくできてしまうので、才能があります。

新卒だった頃の先輩も
まだ新卒で【知識】と【経験】がないんだから
デザインセンスがあるわけない。
と言う意味だったようです。(いや、教えてよ)

そうと分かれば簡単です。

知識と経験は誰にでも蓄積すればいいのです笑

デザインセンスは磨くものです。

特にデザインに関しては、
始めからデザインセンスを備えていないとできないものと
思われがちですが、そんなことはないです。

デザイナーの私にだって、デザインセンスはなかったのですから笑
勉強したか、それを数多くこなしたかの違いなだけなんです。
なにも特別ではありません!誰でもできます!


なので、デザイナーではない方も試しにデザインしてみてください。
何でもいいです。
以前書いた記事を参考に、資料を作ってみるのはどうでしょうか?

rarejob-tech-dept.hatenablog.com

少しデザインの知識があるだけで
受け手の印象が変わってきます。

その先の成功に繋がるかもしれません٩(๑`^´๑)۶

まとめ

デザインセンスについて話してきましたが
今回のお話は【デザインセンス】だけでなく
【センス】という言葉のつくもの全てに言えることだと思います。

自分が○○○のセンスが無いから、、、と諦めてしまっていることがないか
改めて見直してみても良いかもしれません。

それはきっと磨けるスキルなので
【知識】と【経験】を蓄積することで、 今までは諦めていた新しい趣味が見つかるかもしれません!

もちろん、今回のお話は人によって捉え方が違うと思います。
自分なりに解釈し、デザインに触れていただけると嬉しいです(^^♪

それではよい週末を ノシ

身近なデータ分析 〜クラスの継承関係を題材に〜

@hayata-yamamotoです。この記事を書いていたら、小学校の自由研究を思い出しました。当時私は、アリジゴクの採集にハマっていて、研究テーマにしたことがありました。成虫であるウスバカゲロウになるとあっという間に生涯を終えてしまう儚さはなんとも言いがたいものがありますね。

さて、私はEdTech Labという研究開発チームに所属しています。(前回の記事に登場した齋藤と同じです)普段は、Python機械学習のモデル開発やデータ分析をしています。以前、分析チームについては書きましたので、よければそちらもみてください。

rarejob-tech-dept.hatenablog.com rarejob-tech-dept.hatenablog.com

目次

はじめに 

多くのプログラミング言語では、別のクラスをあるクラスに継承させることができます。これにより、共通部分の実装を省きながらユースケースに合わせた追加実装ができるようになります。また、共通部分も上書きすれば、必要な実装に書き換えたりできます。例えば、Djangoでは、以下のようにクラスを継承し必要な実装を加えて使ったりします。

# 引用元: https://docs.djangoproject.com/en/3.0/topics/class-based-views/

from django.http import HttpResponse
from django.views.generic import ListView
from books.models import Book

class BookListView(ListView):
    model = Book

    def head(self, *args, **kwargs):
        last_book = self.get_queryset().latest('publication_date')
        response = HttpResponse()
        # RFC 1123 date format
        response['Last-Modified'] = last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')
        return response

本記事では、この継承に着目します。具体的には、継承を「あるクラス」→「別のクラス」という関係性で捉え、ネットワーク分析の枠組みで分析します。最初にUMLで描いたクラス図を定性的に分析します。次にネットワーク分析の指標を用いて定量的に分析しました。普段何気なく実装しているクラスの継承関係も数学的に捉えなおせば、より客観的で俯瞰的な理解ができると伝われば嬉しいです。

なお、ソースはGitHubに掲載してあります。

github.com

使ったデータ

collections.abc1というPythonの標準モジュールを対象に分析しました。データの選定理由は大きく2つあります。念のためですが、このモジュールを知らなくても問題ないですので安心してください。

  • よく使われるデータセットはもうすでに良い記事がたくさんあるから
  • このモジュールを深く理解したかったから

データ作成に当たっては、公式のドキュメントとcpython2を参考にしています。コレクション抽象基底クラスの継承関係と抽象メソッド、及びMixinについて記載したテーブルが公式には記載されています。このモジュールは、typing3の説明にもしばしば登場します。mypy4などを使用するに当たっては、知っておいて損はありません。

また、分析にあたってCSVデータを別途作成しました。(気を利かせて?)Gremlin形式5になっています。もし興味があれば、Gremlin形式でロードできるグラフDBと合わせて使ってみてください。例えば、AWS Neptuneとかでしょうかね。

$ head -n 5 data/vetices.csv
~id,name:String
v0,"Container"
v1,"Hashable"
v2,"Iterable"
v3,"Iterator"

$ head -n 5 data/edges.csv
~id,~from,~to,~label
e0,v3,v2,extends
e1,v4,v2,extends
e2,v5,v3,extends
e3,v8,v6,extends

ネットワーク、そしてグラフ

普段、ネットワークという言葉をよく耳にします。SNSやインターネット、VPN、サブネットとかネットワークACLなどなど、身近なものからテクニカルなものまで様々あります。ビジネスの文脈ですと、ネットワークというのは人脈のような人同士の繋がりを意味することもあります。要するに、あるものと、別のあるものがつながっている時に、「ネットワーク」という言葉を使いたくなります。このような構造を数学的に扱うのに、グラフが有効です。

グラフと言っても、棒グラフなどの図を意味するわけではありません。宮崎氏によると、『いくつかの点と、二つの点を繋ぐ線からなるもの』6と説明されています。この点を頂点(Vertex)や節点(Node)と呼び、繋ぐ線を辺(Edge)や弧(Arc)と呼びます。また、この辺に向きがあるものを有向グラフ(Directed Graph)、向きがないものを無向グラフ(Undirected Graph)と呼びます。実務でよく目にするグラフといえば、木(Tree)や有向非巡回グラフ(DAG)あたりでしょうか。隣接や(最短)経路なども基礎的で重要ですが、今回は省略します。

以下のリンクは、レ・ミゼラブルに登場するキャラクター相関図をグラフで表現しています。目まぐるしくすぎていくストーリーも、一度立ち止まって、それぞれの登場人物を点と線で結んでみるとより深く理解できるというわけです。まさに、"Connecting the dots"ですね。エモい。

observablehq.com

まずはUML

とはいえ最初からグラフを使おうとすると、難しすぎて心が折れてしまいそうです。ですので、まずはこのモジュールをUMLでクラス図にしてみるところから始めます。ちなみに、UMLは以下の記事でも紹介されています。

rarejob-tech-dept.hatenablog.com

この分析では、大きく二点を確認しました。

  • モジュール全体を把握し、クラスを覚える
  • どのクラスがたくさん継承していそうか、継承されていそうかを直感的に理解する

以下の図を確認すると、直感的には

  • Collection, Set, MappingViewに向いている矢印が多い
  • Collectionは出ていく矢印も多い
  • いくつかエッジを持たないクラスが存在する

とわかるのではないでしょうか。

f:id:hayata-yamamoto:20200525220140p:plain
collections.abc Diagram

いよいよ分析

次に定量的な分析をしてみます。今回の分析には、NetworkX7というライブラリを用いました。分析には以下の3つを用います。

  • 次数中心性 (degree centrality)
  • 媒介中心性 (betweenness centrality)
  • PageRank

中心性とは、「そのノードがネットワークの中でどれくらい重要か」を表す指標と思ってくれれば大丈夫です。人で例えると、次数中心性は「たくさんの人とつながりを持っていること」を評価し、媒介中心性は「その人経由で別の人と繋がることが多いこと」を評価しています。PageRankは、Webページの重要度をはかる指標で被リンクの数を重視します。(一部の例外を除けば)良い記事は、被リンク数が多くなることを期待できます。PageRankはその性質を数値的に表現したものくらいの理解で大丈夫です。色々なページで丁寧に説明されていますので、検索してみると理解が深まるかもしれません。勇気がある人はぜひ、論文8も読んでみてください。

さて、CSVを読み出して有向グラフを作成し、そのグラフに対して必要な計算を実行します。JupyterNotebookの処理を抜粋してみます。

import networkx as nx
import pandas as pd
from typing import Tuple

def pairing(row: pd.Series) -> Tuple[str, str]:
    return (row['~from'], row['~to'])

vertices = pd.read_csv('./data/vertices.csv', index_col=None)
edges_df = pd.read_csv("./data/edges.csv", index_col=None)
edges_df['pair'] = edges_df.apply(pairing, axis=1)

G = nx.DiGraph()
G.add_nodes_from(vertices['~id'])
G.add_edges_from(edges_df.pair)

degree = nx.degree_centrality(G)
between = nx.betweenness_centrality(G)
page_rank = nx.algorithms.pagerank_numpy(G)
df = pd.DataFrame.from_records([degree, between, page_rank], index=['degree', 'betweenness', 'pagerank']).T
df = pd.merge(left=df, right=vertices, left_index=True, right_on='~id').drop('~id', axis=1).set_index('name:String')

このDataFrameをheadすると以下のようなテーブルが取得できます。

name:String degree betweenness pagerank
Container 0.0416667 0 0.0536147
Hashable 0 0 0.019103
Iterable 0.125 0 0.118524
Iterator 0.0833333 0.00181159 0.0353406
Reversible 0.0833333 0.00271739 0.0410238

(よしなに)可視化すると以下のようになります。ノードの大きさは、各指標の値の大きさと比例しています。それぞれの指標によって評価のされ方が異なることがみて取れますね。 f:id:hayata-yamamoto:20200528233423j:plain

最後に、各指標毎にランキングをとって、その合計順位の高い順上位5つを並べると以下のようになります。UMLでの定性分析通り、CollectionやSet, MappingViewが上位にあると確認できました。めでたしめでたし

name:String Sum of rank value
Collection 3
Set 8
Sequence 12.5
MappingView 16.5
Mapping 23.5

おわりに

この記事では、継承をテーマに簡単なネットワーク分析を行いました。ところどころ難しい言葉や解釈に苦労する部分もあったかもしれませんが、普段の何気ないテーマも数学的に捉えなおせば、よりよく理解できることが少しわかっていただけたら嬉しいです。実はそんなに頑張ってテーマを探さなくても、意外と身近に分析のテーマは落ちていて、そこまで難しい手法や実装をしなくても解決できたり調査できたりします。

ネットワーク分析は適用範囲が広く、今回取り上げたテーマの他にもSNSや書籍引用、Webページなど手頃なテーマはたくさんあります。ぜひ手頃なテーマを見つけて勉強してみてください。

引用・参考

時系列予測ライブラリProphet触ってみた

こんにちはEdTech Labの齋藤です。初めての投稿です。 緊急事態宣言が解除されつつありますが、生活リズムが在宅勤務に最適化されてしまったため、出勤が再開された際、寝坊に苦しむこととなりそうで心配な今日この頃です。

さて、今回は最近少し触れる機会のあったProphetというライブラリがとてもよかったので紹介しようと思います。

Prophetとは

facebook社が提供している時系列予測ライブラリで、RおよびpythonAPIが提供されています。 簡単な実装で時系列予測ができるので、さっと時系列予測をしたいときとてもうれしいライブラリです。

実装

実際どれくらい簡単なのか、ProphetのQuiq Startを参考にpythonで実装してみます。 Prophetはfbprophet==0.6を使用しています。

では、データを読み込んで準備をしましょう。

import pandas as pd
from fbprophet import Prophet

df = pd.read_csv('examples.csv')

使用するデータセットはQuiq Startと同じものを使用します。 自前のデータセットを利用する際に注意すべき点として、Quiq Startのようなナイーブな実装では、非連続なデータや1日を超える単位のものは使用しないようにするという点です。これを守らないと、予測がうまくいかないという状況が発生します。 また、それらの対応策はNon-Daily Dataの項目で言及されていますが、今回は割愛します。

では、モデルを作ってみましょう。

m = Prophet() # インスタンス化して
m.fit(df) # データをfittingさせる

これで、先ほどのデータをモデルに入れることができました。 では、予測結果を返してみましょう。

future = m.make_future_dataframe(periods=365) # periodsでどれくらいの期間予測するか決める

forecast = m.predict(future)
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()

これで完了です。 実質7行のコードで時系列予測ができる、とてもうれしい...。

最後に

Quick Startではデフォルトの設定でとてもナイーブな実装となりました。 そのほかにも周期性やトレンドの追加、各種パラメータの設定などリッチな仕様となっていて、ここまで簡単かつ自由に時系列モデリングができるということに感動しました。 自分だけの最強の時系列予測モデルを作っていきましょう。

参考: facebook.github.io