完全なるスクラム初学者が感じたスクフェス初参加の感想

3月16日に1day参加で 「Scrum Fest Kanagawa -春の陣- 」(通称スクフェス)に参加してきました。

この1年ほどはスタートアップのデータ領域の開発者をしていますが、前職時代は長い間データサイエンティスト職をしていました。そのためデータサイエンス系の勉強会イベントにはたくさん参加したり主催したりしていましたが、スクフェスは職種も違うしTLで眺める限りではノリもかなり違いそうだと思い参加を躊躇していました。が、結果参加してとても良かったです。(そして次回もきっと参加する!)

さすがスクラムを嗜好する人たちはイベント内の「コミュニケーション」にもとても気を使って設計されているんだろうなと感銘を受けることがあったので、表題のようなニューカマーが感じたフレッシュ(?)な感想を書いてみました。

アンチハラスメントポリシーの徹底がすごい

技術者の勉強会イベントでもハラスメント注意が厳しくなってきた昨今。そういう流れは知っていましたが、それでもこのイベントでは開会の一番最初に10minほどにわたってアンチハラスメントに対する強いスタンスを示されていることが興味深かったです。アンチハラスメントに当たる例、そういう場面を見たけたら周りの人はどう対応すべきかということを寸劇形式で説明されていました。「そこまでやるか」と思うほど丁寧な実施でした。

性的なハラスメントだけではなく、「スクラムのそんなことも知らないの?w」というような嘲笑もハラスメント対象となるということが説明され、破ったものは運営メンバーも含めて強制退場も辞さないということが念入りに説明されました。初めての参加者、スクラム経験の少ない参加者にとっても非常に安心して参加できる空気がイベント冒頭から醸成されたなと感じました。

カードまで用意されている

discordによるカジュアルさの可視化

スクフェスはchatがdiscordでやり取りされており、全国各地のスクフェスチャンネルを自由に覗き見ることができます。今回のスクフェス神奈川のチャンネルももちろん存在し、当日の発表が行われるのに並行してリアルタイムでかなりの流速で感想がつぶやかれ続けていました。頭に思い浮かんだ単語を反射的につぶやく, 短文の感想をつぶやく軽快な雰囲気があり、「賢いコメントをしなくては」というようなプレッシャーも一切ない雰囲気でした。地味にこういった”カジュアルさの可視化”が意見発信のハードルや会話のハードルを下げているなと感じ、参加者のイベントへのコミットメントを高めているようにも感じました。ツイッターハッシュタグにて同じようにコメントを求めるイベントもありますが、やはりdiscordはいい意味で「届かなくていい人に届かない場所」なので発言の気軽さが段違いだなと感じたり。

オープンスペーステクノロジーOST)というディスカッション形式が非常に効果的かつ面白い

OSTは僕の雑な理解でまとめるなら、「このネタで喋りたい人あつまれ〜〜〜」という自由議論の場なのだと解釈しました。複数の人が「これについて話したい」という好きなネタを発表し、それに賛同する人が適当に集まってグループを作り話を始める。これが複数ネタで同時並行で実施されるという感じ(どの時間にどのネタがどこで話されているかというのは時間割のようにボードに張り出されている)

テーブルが6個(ネタが6個)あるので各時間に興味のあるテーブルに参加する感じ

ユニークなのは、各議論の場に敢えてファシリテーターを用意せず、参加した人たちがリーダーシップをもって自分たちで場を作るということ。自己組織・自律性を求められています。しかし、会社の会議のように必ず発言を求められるわけではなく、「自分にとって学びがある」のであれば無言で参加し続けることをwelcomeとしているし、「自分にとって学びがない」と感じたらいつでも自由に別のネタテーブルに移っても良いというルールらしいです。OSTではその行動も公式に容認しているのでフラッと議論を離れても誰も咎めたり眉をひそめることもしないというルールです。

OSTであげられるネタは特にアジャイル的な内容に沿っている必要はなく完全に自由。イベント内では「ちょっと外に串焼きを食べに行くグループ」というのがあるほど自由でした(自由すぎて僕は最初戸惑いましたw)。一方で喧々諤々に「アジャイルマスターのベストプラクティスを共有するテーブル」もあるし、「初めてスクフェスに参加した人向けに”OST”とは何か」を説明してくれるテーブルもありました。特に後者のようなテーブルを自主的に用意してくれる人がいることこそ、初心者welcomeの精神が現れているスクフェスコミュニティーの良さだと感じました。

今回初めて体験したこのOSTという議論の形態をとても気に入ったのですが、一方で ”オープンスペーステクノロジー”という名前からこういった内容のコンテンツであることが1mmも想像できないのでなんだか名前で損してるな〜と思わなくもない笑

スクラムはエモさを許容する

「私の開発チームが最高なので紹介させてください!!」というLTがあるなど、スクラムが「チームでの達成・成長」を重視する所以なのか、スポーツチームのようなエモさが許容されている雰囲気を感じました。別の界隈から来た身としてはこれはなかなか面白い雰囲気だなぁと。

一般的な仕事の中や、会社の中ではなかなかこういったエモさは表立っては強調されない気がします(例えば、経営層が「うちの会社は最強なんです!!!」としきりに言っていたらなんとなく「大丈夫か?」という気もしてくる…個人の感想かもだけど。)

スプリントレビューをわざわざ会社の食堂スペースで行い、スクラムに関係のない社員でも覗けるようにしてフィードバックを広く得るというようなお祭りイベントにしているという発表もあり、そういった様子を見て「開発チーム、勢いがありますね〜」と社内に評判になっているらしいです。個人的にはそういったお祭りっぽいやり方は好みなのでいつか自分のチームでも真似してみたいなと思ったり😎

「現場」での話を「コミュニティー」でするメリットが大きい/ハードルが低い

例えば、データサイエンスの仕事ではデータは個社の機密度合いが高いのでなかなか社外で発表するハードルが高い。では、その回避策として話をうまく抽象化したりボカシたりして話すのはそれはそれで難しいスキルなので、上手い人じゃないと特に面白みのない一般論的な発表になってしまうことが少なくありません。

それに対して、スクラム界隈のこういったイベントでは、「スクラム」という背骨となるコンテクストを全員が持っているという前提を置きつつ、各現場でそれをどのように改造して上手くやっているか/独自の難しさがあるか というユースケース集として聞くことができるのでエンターテイメント性・学びがたくさんあり聞いていて飽きないのだなと思いました。コミュニティーで自分の現場の問題を話すことで、似た問題を経験した人が他の現場でのプラクティスを教えてくれそうです。現場↔コミュニティーの学びのサイクルがおそらく他の分野より回りやすい分野なのだと思います。今回のikuoさんのkeynoteのお話もそういった内容でした。エモい。

speakerdeck.com

スクラムのコミュニケーションメソッドとメンタリティーがインストール済みである人たちとの会話が心地よすぎる

スクラムフレームワークの中には「チームで仕事をする上で良いとされるコミュニケーション」のプラクティスが埋め込まれていると感じています。上手くスクラムが回るチームは、自然とメンバー間のコミュニケーションも互いに快適/効果的になり、「開発が楽しい」という状態になるそうです。

そういったコミュニケーションのプラクティスがわかっている人が集まるスクフェスでの会話は非常に心地よかったです。傾聴する, 相槌を打つ / 一人が話しすぎない, 話を振る / 過剰なコーチング, ティーチングをしない / 年齢や経験に対して区別をしない 等々。要素を挙げると白々しい感じもしますが、基本姿勢として「人との会話から学ぼう」というアグレッシブな姿勢が強いため、対話相手へのリスペクトと興味がベースにあることが大きな要因だと感じます。初対面の人と対話することが苦手な自分でも、1日中楽しく色んな人とおしゃべりできたのが何よりの証拠だと感じています。始まりから終わりまで心理的安全性が高いイベントでした。

終わりに

なんとなく外から見てると団結力が強そうなイメージがあり、内輪ノリ感も強いのかしらと(けっこう)心配していましがそれは杞憂で、初心者・初参加者に全力で配慮してくれる素晴らしいイベントでした。ただ、スクラムフェスは全国で開催されており、各都市ごとにカラーが違うらしいので特に今回の神奈川開催会が良かったのかもしれません。運営の方々に感謝。各地で雰囲気が違うからこそ全国のスクラムフェスを学会のように回っている人もいるそうです。運営メンバーも有志で行われており、全国を跨いで運営を助けている人がいて各都市で運営ナレッジを伝搬させているようです。コミュニティーがよく出来ている。

夕食兼懇親会の場では飛び入り参加でLT会なども行われ終始賑やかな雰囲気でday1は終わりました。当日の盛り上がりからも遠くない未来にまた神奈川会が開催されるだろうなと感じました。その時はまた参加して今度は自分の現場の学びをコミュニティーで発表したいと思います。

ビール飲みながらやるLTが一番楽しい

これくらいの人数規模が一番密度と熱量が高くて楽しい説

(余談。参加に至った背景)

おそらく今回の参加者の誰よりもスクラム初心者だったと思います。ちょっとそんな背景を。

もともと、アジャイル開発/スクラム開発 という言葉はもちろん知ってはいましたが、なんとなく「一部のエンジニア向けの開発手法だろう」と思い込みこれまでずっとスルーしていました。

転機は2023年末頃からで、転職後半年ほどが経過しプロダクト開発現場におけるタスクや組織の課題感が肌感覚でもわかってきた頃、仕事でコミットしているデータプロダクト開発にありがちな属人性の高さ、それ故の他者のタスクの見えづらさ、他者のコードレビューの難しさ, チームの強みが掛け算できていない感覚等 に困っていました。

しかしそれをうまく言語化したり説得力を持って訴える(他者を巻き込んで改善するムーブメントを作る)ことができないことに苦しさを感じていました。そもそもこれが自分のスキル不足が原因なのか(ただの弱音なのか)、チームの問題なのかが断定できなかったというのも大きかったです。

そんなときにTLでバズっていたikuoさんのRegional Scrum Gathering Tokyo(通称RSGT)スライドに出会いました。内容は、チームがぶち当たっていた問題そのものでした。

speakerdeck.com

我々のチームの問題が、ある種の「あるある状態」であることがわかり、スクラムとやらでそれを解決できるかもしれないことに一縷の希望を持ちました。ちょうど、他チームの人が社内でRSGT動画視聴会を実施されていて、このスライドの発表動画もチームメンバー数名と見て辛い気持ちとなんとかしないとなぁ(なんとかできるかもなぁ)という気持ちを共有できたことがスクラム導入検討のきっかけにもなりました。

スクラムが我々のデータプロダクト開発にfitするかを試す意味でも、一度 ”教科書通りのスクラム” を愚直に試してみようということになりました。4月からスクラムをスタートするべく、現在Sprint0を進めているところです。

ikuoさんのスライド以外にもRSGTで発表された他スライドは非常に参考になるところ多く、自身が開発チームに感じていたモヤモヤを見事に言い当てているぺージなどはスクショを社内のslackに投稿したりしていました(各社で行われていそうですね)。そんなときにTLでスクフェス神奈川が開催されることを知り、keynoteikuoさんだったことがフックになり参加を申し込んだ、というのが経緯です。(スクフェス神奈川に参加したのは、開発チームとして活動を開始して1週間目、スクラムマスターロールに興味があるのでやってみたいと宣言して1週間目のタイミングでした。正真正銘の初心者。)

day1の夜の懇親会にて、スクフェス神奈川主催のseigiさんから「まさにそういった人がきてくれるように開催時期やkeynoteゲストを選んだ側面がある」と懇親会で聞き、まんまとマーケティングにマッチしたのだなぁということを知りました。

僕がいま、僕にとって新しい概念である”スクラム”に胸を踊らせ、「すくらむってすげー!」期に入っていることを自覚しています。このあとダニングクルーガーよろしく坂を転げ落ち、「スクラムなにもわからん(真顔)」「スクラム?場合によっては効果的ですね…(真顔)」になることを楽しみにしています。なにか新しいことを学ぶって楽しいですね。

という感じで、コミュニティーにとても助けられたなという感覚があります。次回のスクフェスでは、「こういった経緯でスクラムを始めたチームがどうなったか」というリアル回顧録をコミュニティーに還元したいなと思っています!

今年は良いお金の使い方が出来たか振り返る by dbt

dbt Advent Calendar 2023 の 14日目の記事になります。
長らくウォッチしてたカレンダーだったのでコミットできて嬉しい✌ qiita.com

タイトルからお察しかもですが、支払明細を整理・集計する "俺々家計簿" 的なものを dbt + duckdb + (Python) で作るお話です。

「ちゃんとお金を使えているか?」

日々の生活において非常に意識的かつ積極的にクレカや電子決済払いをしているタイプです。
最近は小さなスーパーや飲食店でもQRコード決済があり、友人同士の飲み会でもPayPay送金をするため本当に現金を使うシーンが限られてきました。
それらの電子決済情報はマネーフォーワード(マネフォ)に連携しておけば非常に細かい支払いも含めて全て電子的に記録・後からまとめて取得が可能になります。この記事ではそうして得られた2023年1月~11月の約1000件ほどの取引データをdbtで処理して中身を振り返るお話です。(dbtは仕事でもよく使うツールなので、もっと仲良くなるために趣味でも使ってみたかっただけです。)

元々は細かく家計管理をしたい性格ではなく、マネフォのトップにでる「資産総額」が大きく減ったりしなければokくらいの雑さでしか管理をしていません。
どちらかというと、漠然と未来に貯金をするわけではなく、「現在の生活の幸福度を上げるようなお金の使い方ができているか」「お金を良い経験に変えられているか」などを振り返るために今回の趣味開発をしてみようと思いました。

A面として実装の方法、B面ではその集計結果を元に今年は何にお金を使ったのかの振り返りポエムを書きました。

この記事ではdbtの基本部分はいろいろすっ飛ばしていますが、もし興味を持ちご自身でも動かしてみたいと思われたときはこちらの記事内容を事前に履修すれば簡単に理解・構築できると思います!

参考: ローカル環境のみ利用したdbtチュートリアル - Zenn

また、ここではMacOSで動かすことを前提としています。

もくじ

マネーフォワードから支払い明細データを取得する

可能な限りすべての支払い履歴を取得したいと考えたとき、やはりマネーフォワードが一番便利です。自分は有料プラン(月440円ほど)に入っているため、以下のことができます。

  • ありとあらゆる口座・クレカ・その他金融関係サービスをマネフォに連携しまくる
  • マネフォ形式に整形された履歴をcsvで一括ダウンロードする

マネフォのすごいところは連携先のサービスの多さで、メガバンクはもちろん、マイナーな地方銀行CoinCheckビットコイン)、証券口座、iDeCoの年金口座など、ありとあらゆるサービス連携ができます。

また、今回重要な点は、それらの複数の連携先から取得できる情報を「共通のフォーマット」で一括ダウンロードできる点です。これがなかったら各サービスサイトをスクレイピングするなどが必要だったのでさすがにやりませんでした。マネフォ様々。

duckDBをインストールする

今回取り扱うのは個人的な決済データであるため、ここではBigQueryなどのクラウドにデータをあげず、ひとまずローカルで取り扱うことにしてみます。無料かつローカル、そしてdbtと組合せて使うのに評判がいいのは DuckDB みたいです。

参考:  🦆🦆🦆🦆🦆🦆DuckDB入門🦆🦆🦆🦆🦆🦆 - Zenn

DuckDBはpython版とCLI版のどちらでも利用できます。今回はCLI版を入れました。

$ brew install duckdb
$ ./duckdb #起動

csvをDuckDBにロードする

マネフォから取得したcsvファイルのunicodeはcp932になっています。DuckDBはutf-8しか受け取れないため、DuckDBの外でunicode変換を行う必要があります。

import pansdas as pd

df = pd.read_csv('収入・支出詳細_2023-10-01_2023-10-31.csv', encoding='cp932') 
df.to_csv('kakeibo_20231001.csv', index=False, encoding='utf-8')

また、DuckDB CLIPythonでも)はデフォルトでは in-memory にテーブルを保存するため、CLIを終了するとデータは消えてしまいます。データを永続化するには、起動時にファイルを指定する必要があります。

ここでは例として kakeibo.duckdb というファイル名にします。

$ ./duckdb kakeibo.duckdb

DuckDBが起動したら、プロンプトの先頭が "D" となります。
sqlを発行してcsvファイルをテーブルとして保存します(最後のセミコロンを忘れない)

D create table kakeibo_20231001 as select * from read_csv_auto('kakeibo_20231001.csv');

保存できたか確認します。

D select * from kakeibo_20231001;

DuckDB からは cmd + d で抜けれます(DBサーバーのシャットダウン)。終了しても保存したテーブルは消えません。

その他、存在するテーブルの確認 show tables; や テーブルの削除 drop table <テーブル名>; もできます。

dbtのインストール

dbt-core と、 今回は DuckDBを操作するため dbt-duckdb をインストールします。

$ pip install dbt-core dbt-duckdb

dbtの初期設定

dbt init コマンドでdbtのプロジェクトを作成します。ここでは kakeibo_dbt というプロジェクト名にしてみます。
「使用するdatabaseは duckdbか?」と聞かれるので 1 と回答します。

$ dbt init kakeibo_dbt

Which database would you like to use?
[1] duckdb

すると一連のdbtファイルが自動で作成されます。

次に、dbtをインストールすると ~/.dbt/ という隠しフォルダが作られているので、その中にある profile.yml ファイルを編集し、databaseの場所を指定します。
kakeibo_dbt というプロジェクト名で dbt init したので、ファイルにはすでに以下が書かれているかもしれません。(なかったら作る)

kakeibo_dbt:
  outputs:
    dev:
      type: duckdb
      path: dev.duckdb
      threads: 1

    prod:
      type: duckdb
      path: prod.duckdb
      threads: 4

  target: dev

これを以下に書き換えます。path のところを kakeibo.duckdb がある場所に書き換えます。

kakeibo_dbt:
  outputs:
    dev:
      type: duckdb
      path: /Users/ysdyt/git_repositories/kakeibo_app/kakeibo.duckdb
      threads: 1

    prod:
      type: duckdb
      path: prod.duckdb
      threads: 4

  target: dev

これにより dbt がどのduckdb のdatabaseを見に行けばよいかわかるようになりました。

dbt の開発をする

dbtのお作用や基本的な使い方はこちらの記事を参考にしてください(とてもわかりやすいです!)。
ここでは主要なファイルを中心に説明します。

参考: ローカル環境のみ利用したdbtチュートリアル - Zenn

model の開発 - Staging層

今回は以下の様に、models フォルダ以下に staging, dwh, mart フォルダを作り、その下にモデルファイルを作成しています。

まず、データソースをインポートする Staging 層です。
ソース・ファイルを指定する schema_staging.yml の内容は以下。

version: 2

sources:
  - name: main
    description: "kakeibo-model"
    tables:
      - name: kakeibo_20231101
      - name: kakeibo_20231001
      - name: kakeibo_20230901
      - name: kakeibo_20230801
      - name: kakeibo_20230701
      - name: kakeibo_20230601
      - name: kakeibo_20230501
      - name: kakeibo_20230401
      - name: kakeibo_20230301
      - name: kakeibo_20230201
      - name: kakeibo_20230101

今回は1月から11月までの一月ごとに支払い明細のファイルを作成したため、面倒ですが一つつずテーブルを作っています。(1月から11月までまとめてマネフォでcsv出力をして1ファイルにしたほうが楽ではあるが、今回は1ヶ月ごとにデータ確認しながら行ったため。)
ここで指定している -name main とは DuckDB テーブルのスキーマ名を表しています。DuckDB CLI上で select * from information_schema.tables; を実行することでテーブルのスキーマを確認できます。

次に、stg_moneyforward_master.sql にて実際にデータの読み込みと、カラム名の変換だけを行います。

with 
src_moneyforward_master as (
  select * from {{ source('main', 'kakeibo_20231101') }} 
  union all
  select * from {{ source('main', 'kakeibo_20231001') }}
  union all
  select * from {{ source('main', 'kakeibo_20230901') }}
  union all
  select * from {{ source('main', 'kakeibo_20230801') }}
  union all
  select * from {{ source('main', 'kakeibo_20230701') }}
  union all
  select * from {{ source('main', 'kakeibo_20230601') }}
  union all
  select * from {{ source('main', 'kakeibo_20230501') }}
  union all
  select * from {{ source('main', 'kakeibo_20230401') }}
  union all
  select * from {{ source('main', 'kakeibo_20230301') }}
  union all
  select * from {{ source('main', 'kakeibo_20230201') }}
  union all
  select * from {{ source('main', 'kakeibo_20230101') }}
),

final as (
  select
    計算対象::string as valid_frag
    , 日付::string as payment_date
    , 内容::string as detail
    , 金額(円)::int64 as price
    , 保有金融機関::string as financial_institution
    , 大項目::string as category
    , 中項目::string as sub_category
    , メモ::string as memo
    , 振替::string as transfer
    , ID::string as id
  from src_moneyforward_master
)

select * from final

マネフォからダウンロードしたcsvファイルの元々のカラム名は上記のような日本語カラム名になっているため扱いやすいように変換します。DuckDBでは 計算対象::string のような書き方で型変換します。
今回特に必要になるのは 日付, 内容, 金額, 保有金融機関 あたりのカラムになります。例えばこんな感じです。

  • 日付: 支払日を指す。2023-11-25 など。
  • 内容: 何にお金を払ったか。 マクドナルドモバイルオーダー など。
  • 金額: 支出の場合は -720 などのマイナス表記になる。
  • 保有金融機関: 決済方法。 三井住友カード など。クレカや銀行名、その他 Amazon.co.jp などのサービス名が並ぶことも。

Staging層ではゴミデータのクレンジングなどは行わず、一旦全てのデータをインポートするだけにします。

model の開発 - DWH層

Staging層の次はDWH層でデータの加工などを行います。目的に併せてデータを集約したりしますが、ここでは簡単に 有効な収入 を集めるモデルである dwh_income と、 有効な支出 である dwh_expense モデルを作ってみることにします。

dwh_income モデルは以下のような感じです。0円より大きい金額を収入とみなしざっくりと抽出したのち、細かくゴミデータを除外していきます。

with 
import_moneyforward_master as (
  select * from {{ ref('stg_moneyforward_master') }}
),

logical_income as (
  select
    *
  from import_moneyforward_master
  where
    price > 0
),

clean_income as (
  select
    payment_date
    , detail
    , price
    , financial_institution
    , 'income' as label
  from logical_income
  where
    not (financial_institution = 'Amazon.co.jp') -- Amazonのポイントやギフト券は収入としてカウントしない。Amazonからのプラスは全部弾く。
    and not (detail = 'チャージ チャージ&ペイでチャージ,Visa LINE Payクレジットカード' and financial_institution = 'LINE Pay') -- LINE Payのキャンペーン的なものを除外
    and not (detail = '送金受取' and financial_institution = 'LINE Pay')
 (※ もろに人の名前付き口座名などがでてくるため適宜削除しました)

    -- hoge銀行に対するプラスへの対応
    and not (detail = '定額自動入金' and financial_institution = 'hoge銀行') -- 住宅ローン用の口座なので収入としてカウントしない

    -- fuga銀行に対するプラスへの対応
    and not (detail = '利息' and financial_institution = 'fuga銀行') -- 銀行からの利息は面倒なので収入としてカウントしない

    -- 楽天関係のプラスへの対応
    and not (financial_institution = '楽天市場(my Rakuten)') -- 楽天市場でクーポン利用するとプラスが発生するので除外

  order by payment_date
),

final as (
  select * from clean_income
)

select * from final

さてここからが"家計簿集計"の真に面倒くさい部分です。

今回 "収入"としてカウントしたいのは、本業である会社からの給与や、その他本業外からの仕事収入だけにしたいとします。なのでそれ以外の "収入ぽくみえるもの" はゴミデータとして where文で除外したいです。

"収入っぽく見えるゴミデータ"とは、マネフォデータにおいては、例えば銀行間の振替送金や楽天市場, Amazon でのギフト券利用があります。これらは "収入" ではないものの、データ上は 「プラスのお金」としてカウントされます。これらを除外したいため、支払い内容や保有金融機関などを見て、細かく条件を特定して where文で消していきます。面倒くさくはあるのですが、マネフォ側である程度文字列を正規化してくれているおかげもあり、地道に書き出せばすんなり終わったりもします。

これが完了したあとのきれいになった出力は、意図したどおりの "収入一覧" が並んでおり壮観です。月々の給与額はもちろん把握していますが、1年分が1レコードずつ整然と並び、一目瞭然となると軽く感動します(1年よく頑張ったなぁ、みたいな)

全く同じ要領で、dwh_expense モデルも作ります。0円以下の金額を支出とみなしざっくりと抽出したのち、同じく細かくゴミデータを除外していきます。

with 
import_moneyforward_master as (
  select * from {{ ref('stg_moneyforward_master') }}
),

logical_expense as (
  select
    *
  from import_moneyforward_master
  where
    price <= 0 -- kindle unlimitedの書籍などは0円表示になるため、0円も含める
),

clean_expense as (
  select
    payment_date
    , detail
    , price
    , financial_institution
    , 'expense' as label
  from logical_expense
  where 
    not (detail = 'AMAZON.CO.JP' and financial_institution = '三井住友カード') -- Amazon primeカードでの支払い。Amazonの二重引き落としになっているので除外する
    and not (detail = '口座振替' and financial_institution = 'hoge銀行') -- hoge銀行への口座振替。住宅ローンの二重引き落としになっているので除外する
    and not (detail = 'ラクテンカ-ドサ-ビス' and financial_institution = '楽天銀行') -- 楽天カードの合計額が楽天銀行からの引き落とされている。楽天カード支払いの各レコードが別にあるため二重引き落としになっているので除外する
  order by payment_date
),

final as (
  select * from clean_expense
)

select * from final

支出データ側で除外したいレコードの多くは「二重引き落とし」に相当するデータです。

マネフォでは、例えば Amazonのアカウントを連携することで買い物データがそのままマネフォに連携されます。具体的な「購入商品名」もマネフォ側が知ることができ情報もリッチになり便利です。一方で、そのAmazonの支払いを行ったクレカ会社からの決済額レコードも別途マネフォに記録されるため、一つの買い物に対して見た目上は二重の引き落としが発生しているような状態になります。今回はAmazon連携側のリッチなレコードを残し、クレカ会社側のレコードを除外するような処理を行っています。これと似たような処理を他の口座やサービスに対して行っています(除外条件を書く→結果を確認する→除外したいレコードを見つける→それを除外する条件を書く→ ... を満足するまで繰り返す)

余談ですが、マネフォなどの家計管理アプリがいまいちどっぷり使えないのはこれらの例外処理的なものを"良い塩梅"にやりきれないところかなと思っています。自分自身の口座間送金は相殺しててほしいし、上記のような二重引落しっぽいレコードも裏でいい感じにしておいてほしい、でも当然利用者によって残したい/残したくないの意図が違うので一律のルールや機能を強いるわけにもいかないというジレンマがあるのかなと思っています(いや、それはお前がアプリ機能を使いこなせてないだけやで、でしたらすみません。。)

model の開発 - Mart層

最後に、きれいになった収入・支出データを読み込んでjoinして終了です。

{{ config(
  materialized='external', 
  location='/Users/ysdyt/git_repositories/kakeibo_app/export_data/mart_kakeibo_result.csv',
  format='csv'
) }}

with 
import_income as (
  select * from {{ ref('dwh_income') }}
),
import_expense as (
  select * from {{ ref('dwh_expense') }}
),

logical_union as (
  select * from import_income
  union all
  select * from import_expense
),

final as (
  select * from logical_union
)

select * from final

ここでは最終的なデータを csvファイルとして location の場所に別途出力するようにしています。

データを可視化する

せっかくなのでdbt特化型のBIである LightDash を使おうと思いました、が、どうやらLightDashが対応しているDatabaseの中にまだ DuckDB は含まれていないようでしたので泣く泣く撤退。
LightDashは、dbtで定義したmodelやmetricsをそのまま可視化することができるという特徴があり、まだまだ可視化方法は限られていて貧弱なようですが、見た目はLookerライクなので使いやすそうです。ubieさんも積極的に採用・利用されているそうです。

いくつか記事を参考にしましたが、以下あたりがわかりやすかったです。

ここでは大人しくPythonでいくつか集計・可視化します。そしてここからが個人的な1年間のお金の使い方振り返りポエムパートです。
(いろいろ生々しいのでぼんやり色々ボカシます。)

収支の累積の可視化

データがキレイなので収支の推移も簡単に出せます。その月時点での累積金額もプロットすると、トータルで赤字なのかどうか一目瞭然なので節約意識が高まる。。

import pandas as pd

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

# label列がincomeの行だけ抽出する
df_income = df[df['label'] == 'income']

df_income['payment_date'] = pd.to_datetime(df_income['payment_date']) 
df_income = df_income.groupby(pd.Grouper(key='payment_date', freq='M')).sum().reset_index() # payment_dateを月ごとに集約する
df_income['payment_date'] = df_income['payment_date'].dt.strftime('%Y-%m') # payment_dateを月のみにする

df_income.rename(columns={'price': 'price_sum'}, inplace=True)
df_income['label'] = 'income'

# label列がexpenseの行だけ抽出する
df_expense = df[df['label'] == 'expense']

df_expense['payment_date'] = pd.to_datetime(df_expense['payment_date'])
df_expense = df_expense.groupby(pd.Grouper(key='payment_date', freq='M')).sum().reset_index()
df_expense['payment_date'] = df_expense['payment_date'].dt.strftime('%Y-%m')

df_expense['price'] = df_expense['price'].abs() # price列をプラスにする
df_expense.rename(columns={'price': 'price_sum'}, inplace=True)
df_expense['label'] = 'expense'

# df_incomeとdf_expenseを縦に結合する
df_income_expense = pd.concat([df_income, df_expense])

import plotly.graph_objects as go
from plotly.subplots import make_subplots

fig = make_subplots(specs=[[{"secondary_y": True}]]) # 2軸プロットにするときに必要

# 収入・支出の棒グラフ
fig.add_trace(go.Bar(x=df_income_expense[df_income_expense['label'] == 'income']['payment_date'],
                     y=df_income_expense[df_income_expense['label'] == 'income']['price_sum'],
                     name='income'))
fig.add_trace(go.Bar(x=df_income_expense[df_income_expense['label'] == 'expense']['payment_date'],
                     y=df_income_expense[df_income_expense['label'] == 'expense']['price_sum'],
                     name='expense'))
# 収入累積・支出累積の折れ線グラフ
fig.add_trace(go.Scatter(x=df_income_expense[df_income_expense['label'] == 'income']['payment_date'],
                         y=df_income_expense[df_income_expense['label'] == 'income']['price_sum'].cumsum(),
                         name='income_cumsum',
                         line=dict(color='blue', width=2)),
                         secondary_y=True)
fig.add_trace(go.Scatter(x=df_income_expense[df_income_expense['label'] == 'expense']['payment_date'],
                        y=df_income_expense[df_income_expense['label'] == 'expense']['price_sum'].cumsum(),
                        name='expense_cumsum',
                        line=dict(color='red', width=2)),
                        secondary_y=True)

fig.update_layout(title = '収入と支出の推移',
                  xaxis = dict(
                          dtick = 'M1',
                          tickformat='%_y年%_m月',  # 表示フォーマット
                          ),
                  yaxis=dict(
                          title='金額',
                          tickformat=',d' #3桁区切りの数字にする
                          ),
                  yaxis2=dict( # 2軸目の設定
                          title='累積金額',
                          tickformat=',d',
                          showgrid=False,
                          ),
                  legend=dict(
                          bgcolor='white',
                          bordercolor='gray',
                          borderwidth=1,
                          ))
fig.show()

こんな感じのグラフが出せます。(数字とグラフの形はさすがにダミーにしてます)

大きな買い物ランキング

金額が大きい順に並べて眺めてみます。(※住宅ローンや積立投資などのルーティンな支出は除く)

import pandas as pd

df = pd.read_csv('mart_kakeibo_result.csv')
# 支出のレコードのみ抽出
df_expense = df[df['label'] == 'expense']
# 金額が大きい順に並び替える
df_expense.sort_values('price').head(10)

1位. 航空機チケットtoハワイ
6月末に大分遅めな新婚旅行でハワイに行ったときの飛行機代でした。このときが1ドル=144円と円高まっしぐらだったので飛行機も高かったんだ。。

2位. サーフボード(&ウェットスーツなども一式)
去年末に藤沢に引っ越し、海までチャリで15分の距離になったのでサーフィンを始めたときに買ったやつでした。今年の夏は長かったため海も人だらけでデビューするには大混雑な年でした。元を取るために来年も続けないと(冬もやらないと上手くならないとずっと言われている...えぇ...)

3位. 電動チャリ
10年前くらい乗ったロードバイクをついに手放し、人生初の電動チャリ。シェアサイクルで乗ったときの楽さが忘れられずPayPayのポイント還元のときに奮発して購入したやつだった。湘南スタイルよろしく、サーフボードが積載できるように改造しました✌

4位. 京都のホテル1週間分
3月に転職をしたのでその前に1ヶ月弱ほど有給がありました。何をしようかなと思ったときに京都で意味もなくブラブラしたいなということで宿泊してました。いやー、意味のもなく京都ぶらぶらめっちゃ楽しかった。湘南・京都・福岡がいつか住みたい街top3。

5位. 人間ドック
お年頃だし癌家系なのでいよいよちゃんと受けるかーということでやったやつ。高かったなー。ひとまず何も見つからず安心。悪名高いバリウム検査もやり"人生"を体験した。来年からは胃カメラにする。

6&7位. エアコン2台
年末に引っ越した後もケチってエアコンを買ってなかったが流石に夏は無理だろうと人生で初めてエアコンを買った。賃貸でデフォで付いてたあれが、買う+設置工賃がとても高いのだと初めて知って悲鳴を上げた

8位. 長野 Earthboat宿泊
Earthboat | 地球を肌で感じるサウナ付きタイニーホテル というのがある。以前宿泊した素敵なサウナハウスのオーナーが新規に立ち上げたビジネスで、サウナ好きとしては気になっていたのでソッコーで予約して行ってきた。オススメです。

9位. 航空機チケットto台湾
8月に台湾に行ったときの飛行機代。台湾なんて何回行っても良いですからね〜

あとはバラバラしたガジェットなどでした。

2023年は引っ越ししたり転職したりした関係で、そもそも収入も支出もかなりお金関係がガラガラしていた年なのでした。
奥さんとの旅行やアクティビティー、健康や家のことにお金を使ってたようなのでなかなか良いお金使いだったんではないかなと。
良いか悪いかさておき、趣味100%のデカい買い物とかもしてみたい(ファッション趣味の人がこだわりの服を買ったり、車好きの人が念願の車を納車したりしてるの人生楽しそうだなと思う)

今後

こうして結果を眺めてみるとアプリを超えて自作するのもやはり有益だなと感じました。これがデータ設置と dbt run コマンドだけで実行できるのがとても便利です。あとはいろいろあった手動部分も自動化したい。これらをクラウドに持っていき、1週間に一度位で自動実行してLINEに自動プッシュしてくれる君などを作ってみようかなと思います。プライベートデータで好き勝手に自分のためだけの道具を作るのは楽しいですね✌

ネットスーパー立ち上げの裏でデータの人は何をやってるの?

この記事は10X創業6周年アドベントカレンダーの22日目の記事になります。

昨日はFinance・Accounting部のHiroki Maeharaさんが、「FP&Aはイノベーションのガイド役」という記事を公開されていますので是非ご覧ください!

また、昨日6/26が10X社ちょうど創業6周年、ネットスーパーアプリStailerのリリースから3年経ったそうです🎉 振り返れるものが増えていくのは幸せですね!

世はPodcast大航海時代

そんなネットスーパービジネスを展開する10X社ですが、一部界隈では「Podcastの会社」として有名です(僕調べ)

などなど、10X社およびその社員により、為になったり笑えたりする柔剛揃ったいろんなタイプのPodcastが日々発信されています。

こういった 業界への貢献意欲、自己開示の積極性、発信を通しての自己理解,自己研鑽などを楽しみつつ積極的に行われているところ、透明性の高さが僕が10X社(とその社員の方々)を大好きなところの一つです :)

個人の趣味Podcastを始めました

そんな僕も6月で入社三ヶ月を迎えました。

そしてこのタイミングでのアドベントカレンダー企画、せっかくなので22日の本回は、(Podcastの会社らしく)、Podcastにてお届けします!

僕もPodcastガチ勢の一人として、前職では、データ分析に関する話題を話すPodcastをやっていたので、同じようなノリでいろんな界隈の人とまたお話したいなと思い、界隈.chat という趣味の個人podcastを始めました。始めたばかりなのでぜひフォローしてください!

 

今回のおしゃべりのお相手は、僕も所属するグロース本部 データプロダクト部 部長の 天神林さん(@tenjimn)です👏 

改めて、

  • 僕たちがネットスーパービジネスの立ち上げにおいて日々脳みそを捻っている「データの仕事」とはどんなものか
  • ネットスーパー分野においてそれはどう難しい仕事なのか
  • 部署名にもなっている「データプロダクト」とは何か
  • 「データプロダクトマネージャー」とはどう新しい肩書なのか

などを、「入社当時の何もわかってなかった自分」に聞かせたかったぜという感じでおしゃべりしました。

界隈.chat | Podcast on Spotify


天神林さんは 6/10回にて、今回のPodcast内容をさらに詳細に書かれた重厚な記事を書かれています。今回のPodcastはこの記事の導入として聞いてもらえると嬉しいです。

また、同じくデータプロダクト部の野口さん(@tnoguchi15)が書かれたデータプロダクトの成果物"商品マスタ"についての記事も合わせてどうぞ!

 

10X社のネットスーパーのデータ利活用、データプロダクト、データプロダクトマネージャー について興味をもってくださったらぜひお話しましょう〜〜〜!(この声の二人がそのままでてきます笑)

[共通]カジュアル面談 / 株式会社10X

 

このpodcastの続きを自分にも喋らせろ!というアツいおしゃべり好きの方も 界隈.chat ゲスト大歓迎です!(ハッシュタグ #kaiwaichat もしくはお気軽に DM ください!)

 

明日は10X社 3人目社員のソフトウェアエンジニア 石田さん(@wapa5pow)から『10XにSWEとして0->1->10の環境にいたからこそわかる問題の傾向と対策』という記事が公開予定です。タイトルでわかる、絶対に面白いやつやで。

(改めて、本企画の全部の記事はこちら!↓)

Google Domains + GitHub PagesでPodcast番組HPを作ってApple Podcastへ登録する

qiita.com

前回書いた記事ではスタードメイン(Netowl)で取得した .fm ドメインgithub pagesに適応するときの手順を書いたが、今回はgoogle domainsで取得した場合の手順をメモ。

今回は「界隈.chat」という番組名のページを作成したかったので、google domainsで kaiwai.chatドメインを取得した。.chat ドメインは4600円/年なので .fm ドメイン(12000円/年)よりお安い。

yattecastテンプレートをforkして編集する

r7kamura.github.io

  • こちらのテンプレートをforkしてくる。(実際のgithubページはこちら
    • 今回は kaiwaichat というレポジトリ名にした
    • 「settings」>「pages」

  • Branch のところで master /(root) を選択してsaveする
  • しばらくすると「GitHub Pages」のところに「ここにページ公開したで」とURLが出てくる
    • 今回だと https://ysdyt.github.io/kaiwaichat/ となる

  • アクセスするとデフォルトの画面が見える。たったこれだけでwebページの公開ができるのでgithub pages(とyattecastテンプレート)は大変便利 :)  - (特に独自ドメインを当てなくても良いならここで終了となる)

google domains側の設定

  • 先程公開したgithub pagesに独自ドメインを当てていく作業。まずはgoogle domainsにアクセス
  • 事前に購入しておいたドメイン(今回の場合だと kaiwai.chat)を選択し、左メニューにある「DNS」を選択

  • 上記画面のとおりに情報を入力する
    • (Aレコードの値はgithub公式ページから参照した)
    • 1つ目の方の設定での「ホスト名」は空でよい(自動でドメイン kaiwai.chat が埋められるため)
    • 2つ目の方の設定での「データ」部分は ysdyt.github.io とする
      • つまり [github ID].github.io となるように入力する
      • ここを ysdyt.github.io/kaiwaichat とかにするとドメインが正しく当たらないので注意!自分はここにハマって時間を溶かした…
  • 全部入力できたら「保存」。以下のように確定される。

    • (2つ目の「データ」の最後になぜか . が入るが気にしなくてok)
  • DNSが通っていることを確認する

    • ローカルのターミナルなどで dig kaiwai.chat +noall +answer コマンドを打つ
    • 以下のような結果が帰ってきたらok
  • ここまでの設定がうまくいっていたらgithubのリモートレポジトリのコードの中に CNAME ファイルが自動で作成されている(こういうファイル

    • 中身は kaiwai.chat という文字列が入っているのみ
    • (※これはリモートだけに反映されているため、この段階までにすでにgit cloneしてコードをローカルに持っていた場合は一度 git fetch origin master してリモートの編集内容をローカルに取り込む(CNAMEファイルをローカルに持っていくる)必要がある。)

github側の設定

  • 再度githubの当該のレポジトリにて「settings」>「pages」へ
  • 「Custom domain」のところに(今回で言えば)ドメインkaiwai.chat)を入力しSave
    • その下にある「Enforce HTTPS」にチェックが入ってなかったらチェックする
      • これでセキュアな https://~ になる

  • DNS Check in progress → DNS Check in successful とでたら完了

  • 独自ドメインでwebページを公開できるところまで一行もコードを書かずに出来た。便利。あとは当該のレポジトリのコードをgit cloneしてきて編集して画面を整えたりエピソードを追加していく。
    • 詳細は別途

ここまでの参考: GitHub Pages に Google Domains で購入した独自ドメインを設定する - もやし丸の備忘録

Apple podcastへの登録

  • 以下へアクセスし自分のApple IDとパスワードでログインする https://podcastsconnect.apple.com/

  • すでに番組を公開している人は番組が表示されるが、今回は新規登録なので「+」ボタン>「新番組」をクリック

  • RSSフィードがある番組を追加する」をチェックして次へ
  • RSSフィードhttps://kaiwai.chat/feed.xml というふうに、番組ページURL + /feed.xml と登録する。このファイルはyattecastテンプレートが自動で作成してくれているのでとりあえずこのURLを指定すればok
  • 以下のように申請があがり、しばらくは待ち状態になる。申請が通ると登録したメアドにメールがくる。どれくらい時間がかかるかは不明であるが、自分の場合は5日ほどで申請がおりた。

  • 申請が降りるとApple Podcastページで検索を書けると番組が見つかるようになる
    • 申請が降りるとiTunesのURLが発行される。これを _config.ymlitunes_podcast_url: にも書いておけば、番組ページのfooter部分からitunesに飛ぶためのボタンを表示してくれるようになる。

ブレインパッドでの8年間を振り返って

新卒から約8年勤めたブレインパッドを3月に退職しました。

「受託分析」という生存/スケールが難しい事業分野で、ブレインパッド社は着々と大きくなり、そこでデータサイエンティストとしてファーストキャリアを過ごせたことは今後の僕の仕事への価値観/方法論に大きく影響を与えたのだろうと思っています。
なので8年経って思い至ったことを忘れないうちにブログにメモしておこうと思います。
新しい職場でこの考えをアップデートしたり壊したりしていきたい。

僕がいた2015年~2023年の激動のデータ/AI分野の業界の流れについてはこちらのpodcastでも話したので良かったら聞いてください🙂

open.spotify.com

※なお、全ての行末には「知らんけど」が省略されていることをご了承ください。

 

データ分析の仕事

「問題の抽象化・構造化」の価値がますます高くなっている

  • 単発の問題に回答を出すことよりも、複数の/広い範囲の問題を抽象化/構造化し、それに優先順位をつけるという仕事が非常に重要になっている
    • 各現場で各自が日夜頑張って仕事している。しかしそれは”ローカル最適化”している場合が多く、頑張った割に成果が出ない現場が少なくない
    • 必要なのはちょっと高い視点から横串に問題を整理する活動、グローバル最適化とか問題の抽象化とか言われるもの
      • しかし、人間は”グローバル最適化”問題を解くのが非常に苦手(未来はこの部分をAI的なものが担うと思っている)
  • データ分析者こそ問題の抽象化に取り組むべき。スキル/立ち位置共にそれができる一番近い位置にいる。
    • データ分析の人には各現場で発生する具体的なユースケース(要望や課題)が嫌というほど集まっている(データが発生しないビジネスがほぼ存在しなくなってきているため)
    • 複数の現場からあげってくる似たユースケースを知る機会が多い。それらをまとめて抽象化/共通化する(グローバル最適化する)ことが大きな価値となる
    • 局所最適して万事解決なデータ分析はほぼ無く、データは余裕で部署レベルを超え複雑に利用されている。越境や横断が当然求められる
  • 他にも、深いドメイン知識がないと取り組めない問題でも、抽象化/型化することでドメイン知識がない人(その道X年の正社員じゃない業務委託の人など)でも対処できる問題になったりする。問題の整理/抽象化はビジネスのスケール・本質化のためにも本当に尊い活動。

「現実がこい」: DXとはなんだったのか

社内勉強会で「現実がこい」というパンチラインを発した人がいた。これは「DX: デジタル化してトランスフォーメーションする」のではなく、「トランスフォーメーションするために現実(Real)をイジる」という主旨の発言だと思っている。

DeepLが英訳しやすい日本語を書き、stable diffusionがピンとくる呪文をつぶやき、whisperが聞き取りやすい話し方に気をつけ、ChatGPTから適切な回答を引き出しやすい質問を投げる。個人のレベルでやっている「機械によしなにやってもらうために人間側の挙動を変える」ことを、ビジネスでもやるということ。ビジネスになると急に、「人間の活動が複雑すぎてどうしようもないから機械側が合わせろ」となっている。

真のDXとは、従来の人間のワークフロー(現実)をデジタル化することではなく、デジタル化するために人間のワークフローを徹底的に整理/変更することを指すと思っている。DよりもT(transform)がキモ。現実側をtransformしてデジタルに寄せる、現実がデジタルに来るべき。 コンピュータをツールとして利用するのではなく、コンピュータそのものに労働をさせないといけない。「労働力」に昇華するまで自動化を頑張らないといけない。

ここで必ず出てくるのが「デジタル化ができない」という声。現場では「これは絶対に自動化できない」というフレーズを100万回聞くが、「人間が責任をとるべき箇所だから自動化できない(ex.食料品質管理, 医療領域 等)」以外の理由ならどんなに大変でも地道にハードネゴシエーションして機械自動化のための体制へちょっとずつでも変更するしかない。現実はそれが唯一の道だと思う。実はデジタル化できるものが非常に多いし、できないならその作業をいっそ捨てるという選択肢もある。ここを極限まで考え、判断をつけるというのがデータ分析者に求められる”リーダーシップ”の一つだと思っている。

現代こそ「理想からの逆算」が必要

正直、現代の生活はもはや十分過ぎるほど便利である。これ以上なにを望むんだという気さえする。ビジネスは基本的には「誰かの問題の解決」を行う営みであるならば、一般市民が日常生活で「解決したい」と感じる問題は見つかりにくくなっている。

それに伴い、おおよそ解決したはずの過去の問題を現代もこねくり回してるだけとなった仕事も増えている。「なんのためにやってるんだろう」「これ本当に意味があるのか」と思う場面が増えている。なので逆算思考が必要になる。

逆算志向では、「現状の課題の解決」からスタートするのではなく、「100点満点の未来」「Xの未来は斯くあるべし」という出来るかどうかもわからない”強い理想”を出発点にする。スティーブ・ジョブズiPhoneのような。大きな不満が無くなり、過去の延長の仕事が少なくない日本ではこの志向のほうがむしろ必要なのかもしれない。おそらくDXがうまくいかない企業はこういった”強い理想”がまだ持てていないことも大きいと思う。

データ分析は現代における「水戸黄門の印籠」

組織で動く以上、「合意形成」は非常に重要である。

人間は活動の大部分を勘と経験で行っており、ちょっと怪しいな?というところにだけ特に論理的推論を組み立てているように見える。論理的に考えることは大部分の人間には難しいので「納得感」「肌感覚」という勘や経験に近いものが大事にされている。それらのロジカル&肌感覚の両方で人を納得させる(合意をとる)には恐ろしくコストがかかり、ましてや多様な意見を包摂することを目指す現代の組織でコンセンサスをとるための納得コストはもうほぼ誰も払えないところまで来ているように見える。そして組織は硬直化し、意思決定すらできなくなってきている。

現代における納得コストが最も低い道具が「データ」である。データに語らせれば新人の仕事でも偉い人が耳を貸し、肌感覚人間を黙らせることもできる。これはめちゃくちゃ凄いことに思える。

これはまるで水戸黄門が印籠を出せば誰もが黙るというあのシーンに似ている。印籠に逆らって意見を通す方がコストが高いと誰もが理解できるから(ちなみに、同じ働きをする最も原始的な道具は”血筋”だった)。データはとんでもない道具になってしまったなぁ。

一方で、「データは根拠(説明能力)が強すぎる」という悩ましい問題もある。
データ分析者が気をつけたいのは、データの力や全能感に酔いしれ、「データこそ真実!正確!あとはカス!」となること。アニメ「サイコパス 」でも、全知全能AIシステムが効率と合理性を理由に民意を無視し施策を強制的に押し通そうとするのに対して、主人公が「歴史に敬意を払いなさい」と嗜めるシーンがある。 大企業でも一見無意味なシキタリには背景や文脈があり、回り回ってそれが最も合理的だったりその組織にとって最善なことが意外にある。人間の創意工夫の歴史は馬鹿にできない。データの力に溺れてそれらを軽視すると痛い目に会う。 また前項で「理想からの逆算(=強いビジョン)が大切」と書いたが、ビジョンは往々にしてファクトが弱く、説明能力でデータ分析の結果に負けてしまいビジョン無き局所最適の蛸壺に陥るというのを何度も見てきた。これを打開するには意思決定者(=ビジョンを打ち出す人であるべき)がデータ分析(印籠パワー)の功罪を深く理解しておく必要がある。

ちなみに、企業の意思決定における「サイエンス(データ分析)」「アート(斯くあるべしというビジョン)」「クラフト(過去の実験の歴史)」のパワーバランスの重要性について興味がある人はこちらの本がとてもおすすめ。

amzn.to

 

牛刀割鶏: 「最適」を選ぶ難しさ

知識をたくさん持っていることと、”最適”な手法を選択できる能力は別物という話。

昔、某案件にて、膨大な時間と知恵を総動員して作った深層学習モデルを、先輩が数日で作った枯れた機械学習モデルが精度面で肉薄するという、ある意味でゾッとする出来事があった(簡単な方法で出来たなら今までの無駄な時間をどうするとクライアントから怒られる) 結果、このシチュエーションではとにかく精度の高さを優先する(かつ、PRのために深層学習モデルが好ましい)となり事なきを得た。

この手の話はとてもよくあることで、実際に「最適な手法を選ぶ」作業は想像よりもややこしく現場によって常に「最適」が異なる。精度や実行速度などのわかりやすい指標だけではなく、PRの派手さ・既存システムとの連携難易度・現場関係者のリテラシー・現場の稼働可能人数・予算/工数 など、非明示なパラメーターの機微に大きく影響される。これらは知識の多さよりもコミュニケーションの多さ, 裏の意図を汲み取る空気を読む力みたいなものがモノを言う場合も多い。

この出来事をみて、ベネズエラ人の先輩が教えてくれた中国の故事が「牛刀割鶏(鶏を捌くのに牛用の包丁はいらない)」だった。

タスクが難しいほど高度な武器が必要ではなく、なぜタスクが難しいのかをまず疑い、その構成要素を理解し分解して、まずは最小構成の手段でやってみる。「もっと簡単な方法があるとおもうんだけどな〜」「先にやるべきことがあると思うんだけどな〜」と自問自答する癖はこの経験から来ている。

プロジェクトマネージャーという役割

マネージャー志向: どこまでを自分のコントローラブルな範囲としたいか

データ分析者がマネジメント層になりたくないというのが多くの企業で課題らしい。

データ分析やエンジニアリングは現場で手を動かすのがあまりにも楽しいので、相対的にマネジメントのほうが楽しくなさそうに(外側からは)見えるのは仕方ない。

マネジメントと一口に言っても、プロジェクトのマネジメントなのかピープルマネジメントも含むのかなどいろんな要素が絡むのでこれもまた外からみてマネジメントの仕事がよくわからなくなってる要因になってる。

エウレカ社の奥村さんがマネジメントの難しさや楽しさについてnoteを書かれている。

note.com

僕が共感したのは、「組織や仕事についてのモヤモヤを直接自分が裁量を持って関わるほうが実は心理的にヘルシー」という部分。

データ分析を仕事にしている人は、改善志向や責任感が強い人が多い印象なので、「飲み会でグチグチ仕事の文句を言ってるだけの自分が嫌い」という人は少なくないのではと思う。そういう人は実はマネジメントをやるほうが一定イキイキ働けるのではと思っている。

腹落ちしてない指示やtop downな命令による失敗はムカつくが、自分が考えて、自分がメンバーに指示して、それでも失敗したら自分の反省しか残らない。こちらのほうが実は余程メンタルに健全だし何より成功しても自己肯定感が上がるし、失敗しても学びを得られるので結果的に得をするのは自分とも言える人が多いのではと思う。

メンバー、PM、組織マネージャーでコントローラブルな範囲は当然増えていく。

メンバーは特定のタスクだけについてコントローラブルに見えるが、本当はそれすらもPMの意向で変えられるので実は実質的にメンバーがコントローラブルなものは何もない(どれくらい裁量が渡されるかはPM次第という意味で)。

PMはプロジェクトについてコントローラブルに見えるが受託分析は実は違うと感じる。メンバーに対してコントローラブルなので範囲は少し増えてはいるが、プロジェクトについてはクライアントの鶴の一声でガラポンされるので受託PMでもコントローラブルではない。「PMはそこもコントローラブルにするためにクライアントと”パートナー”になるべき」といわれるが、それは受託会社側の理想論であり、クライアント側はなんだかんだやはりそこまで期待していない場合が少なくない。受託PM側が「ガラポンが納得できないのであなたの上司にかけ合わせてください、説得してみせます」と言われてもクライアントも困ることは目に見ている。僕が受託分析の限界だと感じているのはこのあたりかもしれない。受託分析ではなんだかんだ解決できる問題のスコープが狭い。

もっと本質的な問題解決をしたいなら、当該企業の社員になり、その社内でもっとコントロール範囲の広い(偉い)ポジションを取るしかないのではと思う。データ分析者はもっと組織内のポジションを上がって意思決定層に発言権を得なければ意味のある仕事ができないという話は Data Analyst Meetup Vol.10 でも強く語られている。

偉くなってコントローラブルな範囲が増えるとストレスが増えるというが、少ないからこそストレスが増えるという人もいる。データ分析者はとりあえずポジティブにPMポジションを目指して体験してみるのが良いとは思う(ダメだったら気楽にその時に考えよう)

PM育成の難しさ: 向き不向きが大きく現れる

  • (様々な意見があることを理解しつつ、)データ分析に趣向がある人を”教育”して一人前のPMにすることはほとんど現実的ではないかもと思っている派
  • プロジェクト/プロダクト/人の管理 に対する”マネジメント”と呼ばれるタスクには、人によって性格なども含めた向き不向きがあるように思える
  • そしてその向き不向きは大卒年齢くらいにはほぼ決まっているように感じる。その段階で「向いてなさそう」という人はやっぱり向いていない可能性が高い。もちろん努力によってできなくはないが、ヒソカのいうメモリの無駄遣い 的な状態になり本人もツライ。そうなりがちなのがマネジメントという役割な気がする。
  • 育成としてできることといえば、向いている人に対してはごちゃごちゃ言わない/邪魔をしない/ストレッチな挑戦の場を提供しサポートする/既知の知見はバンバン与える くらい。そして向いていない人には強いてPMをやらせることをしないことがお互いの為に良いと思う。
  • ただし、PMにも様々なレベルがあり、1.小規模PM(メンバー ~1,2人)、2.中規模PM(メンバー ~3,4人)、3.大規模PM(メンバー 全部で10人前後)があるとして、小規模PMは向き不向き関係なく全員やってみるべき。
    • PMがどういう気持ち, 何を気にするのかわかる。仮に向いていなくてPMを辞めたとしてもこの経験は必ず活きる。
    • 2,3からは向いてない人には努力でどうこうするには圧倒的にコスパとメンタルに悪いため向いている人だけチャレンジすれば良い。しかし、社歴が増えるほど多くの企業では「どれだけデカい案件のPMができるか」が評価の大きなところを占めるっぽいのでレベル1で留まる代わりに評価は渋くなる覚悟が必要になる。大規模PMはできないが技術力は組織の中でもtopN%に入る、的な生き方が評価される会社なら良いがそれは会社に寄る。
  • マネジメント気質みたいなものは不思議で、一定の性癖のようなものに感じる。仕切りたがり・当事者意識/使命感意識が謎に高い・人に指図されるのが嫌・自信家、承認欲求が一定以上高い などなどの、仕事とは関係ないその人の性格にも大きく依存している気がする。めちゃくちゃ端的には、学校などで”学級委員長”をやったことがあるようなタイプが謎にそういう気質を持っていたりするような印象がある(しらんけど)

良い問題がチームをリードする: PMは問題を言語化してナンボ

akirachiku.com

「PMの最も大切なスキルのうちの一つは影響力によって向かう方向を示していく事である」というフレーズがある。自分もこれに同意する。

ここでいう”影響力”とはその人がこれまでに培ってきたもののことを指し、それは技術力だったり、コミュニケーション力だったり、その人が得意な武器なら何でもよくて、それを使って”良い問題”を示しチームのテンションを上げ、解決を目指す。

”良い問題”の定義の方法もその時々によって違う。僕の好きな話に「リーダーシップとマネジメントは違う」というやつがある。

大体の案件においてPMが示すべき”良い問題”は「マネジメント」側に書かれていること、つまり”複雑性の縮減”を実行するために生まれる場合がほとんどと思う。ただ、分析のPJにおいては「やってみんとわからんな〜」という意味で、”不確実性への対応” をやったり、「データでなんかできませんか」と依頼され ”あるべき姿を示す” など「リーダーシップ」側のことをやっている場合も少なくない。どちらが得意か、テンションが上がるかというのも人によって異なる。分析PJは目指すべき方向、可能な選択肢がとても多い。 だからこそ「こっちに進むぞ」という明確な意思表示がとても重要で、PJがコケるorつまらないものになるか否かはPMの示す「向かう方向次第」な部分がけっこうある。

分析PJはともすればすぐに脇道に逸れる。なので「向かうべき方向」は必ず目に付く場所に置き、定期的に振り返る必要がある。「その場その場で喋って伝える」はダメで、言葉はすぐに霧散する。テキストに書き出して誰でもいつでも見れるようにすることが本当の「言語化」。パターンや説明することが多すぎて書いてるとキリが無いという気持ちになる。わかる。でもそれがPMの必須の仕事なので。

組織

All you need is “企業文化”: 「いいやつ」と働く

ブレインパッドのデータサイエンス部の好きだったところの一つは「ヤバい人」がいないところだった。 話しかけても塩対応されることはないし、教えて欲しいとお願いすると1を聞いて10教えてくれる。最高だった。これはなぜかなと考えたがまだ自分のなかでは上手い回答が見つけられていない。僕が特に好きだった人たちは「社会に貢献したい」「自身のスキルを伸ばしたい」「データ活⽤の促進を通じて持続可能な未来をつくるの理念が好き」という点が良く共通していた印象があるのでこのあたりに何かある気はしている。

いろいろな技術的課題も、ビジネス的課題も、結局は ”人間関係が良いかどうか” に帰着している気が年々増している。

人間関係の良さを作るためには一定の人間的同質性を共有していること、そしてそれによってコンセンサスコストが低いことが必要っぽいが、同質過ぎてもダメっぽいので難しい。それらを含む、組織の雰囲気を伝える定量化できない微妙な塩梅のパラメータを醸し出しているのが「企業文化」というやつっぽい。企業文化が存在すると、この組織に入るとどういう人は幸せになってどういう人はそうならないかがわりとはっきりとわかる。Netflix社にも「頭はいいけど嫌な奴、お断り」という文化があるらしい。

確かに転職活動をしていて、はっきりと企業文化を伝えてくるところとそうじゃないところがあって面白かった。人が減る日本にとって優秀な人の獲得はますます難しくなっていくが、なぜか優秀な人ほど「なんとなく会社の雰囲気が良さそうだったから」という曖昧な入社理由な人が多い印象がある。はっきり言って外から見る程度でその会社が良いかどうかは給料の多寡や社員の在職年数くらいでしか察することができない。でも実際にはそれを最低条件とした上で「いい人と働けそうな”雰囲気”を感じられたか」に尽きる。

「なんとなく雰囲気が良い」はおそらく理詰めで作れるものではなく、ぼんやりできあがるものでもなく、一部の人たちが中心となって発している”熱”がじんわりと時間をかけて周囲にも伝搬して薫ってきているものと思う。この熱源を特定し、冷水をかけないことが組織において重要。これからもいい人たちと働きたい。

大企業における空気を読んだ越権: アホのフリをしてどんどんやっちゃう

大人社会には良い意味でも悪い意味でもグレーゾーンが存在し、グレーゾーンを触るときは「言うな聞くな」というお作法が存在する。偉い人は立場上、「XXしてもいいですか?」と聞かれるとダメと答えざるを得ないときがあるし、また、グレーゾーンにも関わらず堂々とOKだと言いふらす行為も目を瞑ることができなくなる。

アホのフリをして(わかっているがわかっていないフリをして)やっちゃうというのも、停滞する空気感が漂う場から変化するためには一定必要になる場面がある。ポイントはアホの「フリ」であり、空気を読む(”アウト”と”グレーゾーン”の境界線に見当がついている)ことである。本当にアホなことをするとヤバいので、このニュアンスがピンとこない人にはオススメしない。

何かを変えるために必要なのは具体的な「行動」のみである。そして、現体制に対し真正面から膨大なコストを払ってヘトヘトになりながら行動して途中で力尽きるよりも、グレーゾーンのお作法を守って具体的な行動を積み重ねて切り開かれた道が結果的に正道となることもある。

ただ、この方法を全面的に奨励するわけではない。停滞した現場で新たに何かをスタートさせるときには一定役に立つが、ある程度長期スパンの視野を持っておかないと死ぬしめちゃくちゃ組織の迷惑になる

 

業界/キャリア

データ分析者がロードマップをつくる

草野社長がよくお話されている&こちらのnote(日本のAI導入効果がアメリカの7分の1程度しかないのはなぜなのか)でも言及されているように日本のデータ活用の課題は、

外部ベンダの力なしにはプロダクトの企画、開発を行うことができない

リーダー層に、プロダクトマネージャー型の人材が不足している

7割超の企業でDX推進のビジョン・ロードマップがない

あたりというのは現場の肌感覚としても実感している。

つまり端的には我々のようなデータ分析者が

  • 受託(=外部ベンダ)としてではなく、事業会社に入り、
  • 発言権と実行権があるポジションに就き、
  • AI活用のビジョンロードマップを我々が引いて推進する

ことだと思う。僕は前項のような理由で受託分析には掘れる限界があると思うので事業会社に行ってみようと思う。

これまでの案件経験から、とくに3つ目の「ビジョン・ロードマップがない」というのが最もクリティカルな課題と感じている。

ロードマップがないため全体最適ができず、過去の延長として各現場で効果の高くない個別最適を頑張っているというように見える。「生産性が低い」はこれのことだと思う。 特に最近の事業ロードマップにはデータ戦略が不可欠であるが、これははっきり言ってデータ分析経験者しか立案ができないのではないかと思う。なのでデータ分析者は組織の中でもっと偉くなってロードマップをひいて推進できるポジションまで上がらないと企業の推進・立て直しは難しいのではと思う。僕は以下のツイートに全面的に賛成している。データ分析者は現場の課題解決で終わらず、会社の戦略に口出ししてナンボだと感じる。

 

妄想未来: 定量化できないものの価値が見直される

「データ化できないが重要なのでどうにかしたい(分析して改善したい)」というニーズが増える気がする。

何を言ってるかわからねーと思うが僕もわからない。ただこの分野にとても関心がある。具体例を一つ出すとこれ系の話。例えばコミュニティーのハブになっているような人でも金銭貢献などわかりやすい評価指標が確認できなければ需要ではない(いなくても問題ない)とみなされるような話。

togetter.com

資本主義がうまく駆動しない領域があることが目立ってきている。

資本主義は「定量できること」が前提なので、資本主義がぶっ壊れた世界では定量化できないものがなんとかして人間に認知可能な状態にされ大事にされそう。

定量データ分析をしていた人だからこそ、非定量分析の方法も検討できるはず。定量化できるものはほとんどがAIによって自動運用・管理されるが、定量化できない世界を人間がより大切に感じて守っていくというのが次の世界線になりそう(SFの世界です)

定量化できないのでこれらの活動はお金にはならない。ただ、FIREした億り人やIPOした起業家など、経済的には一度人生が”あがった”人は金銭的制約から外れるとどうやら「お金換算されないが中長期的に必ず社会に対して価値がありそうなこと(わかりやすいものだとコミュニティ活動、教育事業、自然保護等)」に精を出す傾向がある。人類にとってもその方が幸福な未来に見えるけどどうでしょうね。

同時期に退職された優秀なデータサイエンティストの先輩も「生物の多様性を守る」ことの価値をビジネス側にどうやって示すかというお仕事をされるそう。今は99%の人がピンとこないと思うが、おそらくこういった「お金にならないしデータ化が困難だけどどうにかして改善したいこと」系の仕事が今後は増えていくと思っている。

DSのネクストキャリアのひとつ: Data Product Manager へのお誘い

僕はキャリア論について本当に興味がないのと、実際になにもわからん、わからんし結局は各自そのときに好きなことをやったら良いと思ってる派。

そんな自分でもちょっと面白そうだなと思って次の職場(10X社)でチャレンジするのが Data Product Manager(DPM)というポジションなのでその宣伝をしたいと思う。同志が見つかると嬉しい。

DPMや、Data as Product という考え方については次のスライドがわかりやすい。

speakerdeck.com

 

約三行要約

  • データがプロダクトに並んで重要になった。かつてはデータはプロダクトの付属品だった。今は違う。データ単体で販売されたり、むしろプロダクトよりも蓄積されたデータの方が価値があると見られるプロダクトも出てきた。
  • PdMと並び、DPMというポジションが確立しつつある。DPMはプロダクトが生成するデータの価値をさらに高めることを専門に動く特化型PM職種の一種。
    • PdMは忙しいのでデータの世話まで見きれない、かつデータ活用は専門知識が必要なのでそもそもPdM一人に背負わせるのは酷すぎる。
    • 現実的にはデータ部分だけでもPdMからもう少し切り離す必要があり、それをDPMが担う。
  • 各機能や各担当チームの中では局所的にデータ利活用が進んでいても、全体を見るとデータの不整合が発生しているということはよくある。DPMはプロダクト全体を中長期の視点でも考え、データの不整合が発生しないように目を光らせる人。
    • データの不整合への対応というだけではなく、企業戦略とも合致し、中長期で変更に強いデータパイプライン/データ基盤を作っていく役目。これはデータ分析者かつビジネス側ともツーカーで会話できるより高いスキルが必要となる。(現在の日本の大企業はこのあたりが決定的にできていないと感じる)

「転職するなら事業会社いきたいなー、でも特にやりたいこととかドメインはないんだよなー」という人はもしかすると上記のような観点でデータに携わるDPMというポジションは刺さるかもしれない。新分野でまだベストプラクティスなども溜まってないので新たな学びがたくさんあるようにも感じる。特に最後の「企業の戦略に合わせてデータ活用できるためのデータパイプラインを設計する」というミッションは並のデータ人材では難しく、「ビジネスとのすり合わせ」と「手を動かすデータ分析」の両方をやってきた人じゃないと難しいのではと思ったりする。問題が難しい分、きっと解く楽しさがあるはず。

PdMはプロダクトの次の方針をチームに説明するためにデータ分析の結果を示してチームをリードする。なのでデータアナリストがPdMになるのはシナジーがあると思っていたが、DPMのほうがさらにデータ分析キャリア側から越境しやすいかもしれない。

これからのビジネスでは、GPTのような汎用的大規模言語モデルをいくつか組み合わせたものをどこの会社でも当たり前かつコア機能として利用するようになると思っている。それに伴い、各企業がもつ独自データで追加学習した各社オリジナルのAIを各社独自に作る流れがあると思う。DPMが綺麗なデータやパイプラインを作っていると、それがそのまま企業AIを育てる揺りかごになるかもと妄想している。今後のビジネスの中核となる企業AIはDPMが育てるのかもしれない(しらんけど)

 

と、途中でさらっと書きましたが次は10X社でデータプロダクトマネージャーとして働きます!楽しみ!

 

(P.S)

大昔から、データサイエンスの部では退職者が最後に何かしら卒業発表をしていくというお遊びイベントをやるのですが、今回は僕とほぼ同時期に9年目の先輩も退職という古参メンバーx2名の合同イベントとなり、オンライン/オフライン併せて100名くらいの人たちに追い出ししてもらった。

 

そもそも8年もいるなんて自分が一番思っていなかったのでなんだか実家を出て一人暮らしを始めるときの寂しい気持ちを思い出した…

創業19年目を迎えたブレインパッドは、僕の退職直後に社長交代のビッグニュースも流れ、これからまたもう一段階組織も進化するのだと思う。節目のタイミングに退職となり後追いでまたなんだか感慨深い気持ちになってしまった。

僕にとってとても充実したファーストキャリアになりました。「元ブレインパッドの人やっぱりすごいな」と業界で言われるように新しい職場でも頑張りたい。

最終発表イベントの後にみんなで:)

最終日に貰った19年記念お菓子

リーダーシップとマネジメントは違う

「良いマネージャーとは」という話をするときに、「良いリーダー(またはリーダーシップ)」の話を混ぜて話されていることがあるが、その2つは本質的に全然別物だという話

open.spotify.com

 

出典は早稲田大学ビジネススクールの杉浦教授のものらしい

2022年振り返り

1月

雪山(北横岳)に登った

 

spacemarketでサウナ付きの自宅を借りてサウナパーティーした

 

2月

家の近くに最高のサウナを見つけてアホほど通う

 

昔作ったアプリを全部イチからpythonで再実装。友人の結婚式で使ってもらう実績解除。

 

退職時の寄せ書きが味気なくて嫌だったので、「声の退職祝い」を作ってプレゼントした。地味にめちゃくちゃ良いサービスだと思う

 

「千年婚姻届」についてビジコンで発表。学生部門として賞をもらったビジコンで、今度は招待講演として発表させてもらった。婚姻届はこちらから購入できます

speakerdeck.com

 

学会発表。仕事の一部が学会で発表された。

 

3月

α7Ⅳ買った。動画をたくさん撮るようになった。やはり写真よりも残る情報量が多いので動画の方が好き

 

mameya kakeruとても良かった。今年は清澄白河に行くことが多かった

 

4月

オフィス移転。コロナ期間をのぞいても6年は毎日通っていた白金台のオフィスだが感慨は意外に無かったな...

 

長野の最高のサウナx2に行ってきた

www.youtube.com

 

5月

鎌倉で指輪を自作し、島根 出雲市役所で自作の千年婚姻届を提出してきた(旅行vlogを年内にupしようとしたらタイムオーバー)

 

6月

雷が鳴るほどの土砂降りのなか、水芭蕉シーズンの尾瀬にいってきた。尾瀬の山小屋にサウナができるらしいのでまたトライしたい

 

新オフィス初出社。夜景が綺麗な六本木一丁目のオフィス

 

B43で家計管理を始めた。今年一番の体験のサービス。重宝している。

 

8月

オートキャンプすずらんの川サウナが最高だった、おすすめ

 

9月

白馬に登った。下山後に宿泊したホテル五龍館のサウナが今年のベストサウナだった、絶対にまた行きたい

 

大学時代の友人とヤッホーfmというpodcastを始めた(が、かなり更新をサボっている)

 

10月

Data Analyst Meetup Vol.10を開催した。オンライン/オフライン合わせて700人弱の申し込みとなるマンモスイベントとなった。内容は一部podcastで公開した

 

パートナーが骨折。緊急手術のすえ長野の病院にそのまま3週間入院することに(今は無事退院)。山場での事故は山岳事故扱いになり警察への報告が義務付けられているらしい、そしてyahooニュースへ...。人生いつ何が起こるかわからないという気持ちを新たにした。あと保険は大切。

 

11月

5月から家を探し始め、紆余曲折あって藤沢市に家を買って引っ越した。藤沢は大学院生のときに住んでいた時ぶり。骨折につきまだウロウロできていないが、夏になったら湘南ライフを満喫したい。

 

12月

自作キーボード沼にハマってしまった。抱いて寝れるほどとても気に入っている

 

(おまけ)podcastの更新

始めてから3年経つ白金鉱業.FMを今年も13本更新していた、エラい!我ながら無くなったら惜しい番組、良い番組だと思うことが継続の秘訣かもしれない。できるだけ頑張って放送を続けたい。