IT企業で島対抗・お菓子バトルをやった結果をRで振り返る

  • 5
    いいね
  • 0
    コメント

まえおき

Hamee Advent Calendar 23日目の記事です。サンタさんには数年振りに2016ピースパズルをお願いしました。
(昨年サンタさんにお願いしたWiiUとスプラトゥーンのセットはお正月に自分で買いました。)

去年のHameeアドカレでは、Rを使った簡単な分析準備編ということで箱根駅伝の順位相関をやってみたので、今年はもうちょっと突っ込んだ分析を…と思って当初「Rおてがる分析(実践編)」というのを考えていましたが、なかなかデータのネタが見当たらず。。

そこで今回は、今Hamee開発部でやっている面白い取り組みをテーマに、今年もかんたんな分析をちょこっとやってみたいと思います。

お菓子アイランド対抗戦

概要

弊社では2,3年前から 業務中の糖分補給大事だよね という信念のもと、共有スペースにお菓子と募金箱が置かれていて、「自由にお菓子を取っていいよ、お菓子を食べる人は募金よろしくね」という制度がありました。
結構みんなお菓子を食べるし募金もするし、わりと募金箱にはお金が入っていて、定期的に誰かが昼休みに最寄りのドンキホーテでお菓子を買って補充してくれたりしていました。
そんな中、ちょっとおもしろいことやろうよ的なノリで(チームワーク向上のため)、お菓子バトルをやろうという話になりました。

ルール

  • 島(だいたい6〜8人の業務デスクのかたまりを島と呼ぶ)ごとに、募金箱とお菓子エリアを設置する
  • 島の人間は、募金箱の中のお金を使って、お菓子を補充・提供する
    • 最初に各島には700円ずつ配布する
    • 募金箱のお金で足りない場合は 資金投入額 として自分のお金を出してお菓子を購入しても良い
  • 島以外の人間は、気に入ったお菓子のある島に募金をしたら、そこに置いてあるお菓子を食べて良い(これまで通り、食べる量(回数)と募金額は各自の良心に委ねる)
  • 募金箱の金額 - 資金投入額 = 売上 とし、最終日に1番売上金額が多かった島が優勝
  • 食べ物はすべてお菓子とする

ということで、12月の1ヶ月間、各島による熾烈なお菓子バトルが始まりました。

途中結果

まだ最終集計前なんですが、先週集計時の結果です。

No 島名 募金額 資金投入額
1 シャーベッ島 1060 340
2 チョコレー諸島 12232 25484
3 グラニュー島 3378 2442
4 フルーツタル島 5682 19593
5 ヨーグル島 100 749

※ チョコレー諸島は、本社の島1つと東京営業所との合同チーム

結果を分析してみる

資金投入額と募金額にはどのような関係があるかを調べてみます。
ここでRの出番です。

まず、上記のデータをMySQLに投入し、それをRから呼び出します。
MySQLとRの接続はいろんな記事で紹介されている通りですが、簡単におさらい。

RにRMySQLを導入する

初回にインストールしておきます。最初に1回やっておけば良い作業です。

> install.packages("DBI")
> install.packages("RMySQL")

ここからは通常時のアクセスのやり方です。

> library(RMySQL)
 要求されたパッケージ DBI をロード中です

> md <- dbDriver("MySQL")

> dbconnector <- dbConnect(md, dbname="island", user="root", password="root")

> island.sales <- dbGetQuery(dbconnector, "SELECT * FROM island_sales")

> dbDisconnect(dbconnector) # 格納が終わったら接続を閉じておく

これで変数island.salesにデータを投入できました。

データを客観的に眺める

> class(island.sales)
[1] "data.frame"

このdata.frameというのが型です。
DBから取得しているのでデータフレーム(枠、マトリクス形式)ですが、1要素であればcharacter, numericなどがあります。
投入したデータの情報をざっと確認してみます。

# 全データ表示
> island.sales 
  id benefaction capital
1  1        1060     340
2  2       12232   25484
3  3        3378    2442
4  4        5682   19593
5  5         100     749

# 各カラムのみのデータ表示
> island.sales$benefaction
[1]  1060 12232  3378  5682   100

# 平均
> mean(island.sales$benefaction) 
[1] 4490.4

# 最大値
> max(island.sales$benefaction) 
[1] 12232

# 列ごとのサマリ(最小値, 第1四分位点, 中央値, 平均, 第3四分位点, 最大値)
> summary(island.sales)
       id     benefaction       capital     
 Min.   :1   Min.   :  100   Min.   :  340  
 1st Qu.:2   1st Qu.: 1060   1st Qu.:  749  
 Median :3   Median : 3378   Median : 2442  
 Mean   :3   Mean   : 4490   Mean   : 9722  
 3rd Qu.:4   3rd Qu.: 5682   3rd Qu.:19593  
 Max.   :5   Max.   :12232   Max.   :25484   

summaryも出してみましたが、今回は5チーム対抗なので四分位点は2,4位になってしまっています。
本来であればこのあたりを考える場合はもう少しサンプル数が欲しいですね。

data.frameの編集

ここで上記のsummaryを見ていると、MySQLのテーブルで定義していたid列は集計には不要のようです。
id列を集計しても連番なので意味をもたない)
一方で、集計した募金額と資金投入額しか入れていなかったので「売上(sales)」が欲しくなります。
なのでid列を削除して、benefaction-capitalをしたsales列を追加しましょう。

# data.flameから列を削除する(=1列目を削除し、2〜3列目を残す)
> island.sales <- island.sales[c(2,3)]

> island.sales
  benefaction capital
1        1060     340
2       12232   25484
3        3378    2442
4        5682   19593
5         100     749

# 募金額 - 資金投入額 = 売上 を算出
> island.sales$benefaction - island.sales$capital
[1]    720 -13252    936 -13911   -649

# 上記の結果をtransformを使ってdata.flameに追加
> island.sales <- transform(island.sales, sales=island.sales$benefaction - island.sales$capital)

> island.sales
  benefaction capital  sales
1        1060     340    720
2       12232   25484 -13252
3        3378    2442    936
4        5682   19593 -13911
5         100     749   -649

Rだとこのあたりもお手軽ですね:v:( 'ω' ):v:

相関関係を調べる

続いて、プロットに出してみます。
3指標のデータをそれぞれ組み合わせで見るとこんな感じになりました。

> pairs(island.sales)

スクリーンショット 2016-12-23 21.38.40.png

ちなみに、募金額と資金投入額など、2指標に絞ってみる場合はpairsではなくplotを利用します。
x軸が募金額、y軸が資金投入額です。(pairsの左真ん中と同じものです)

> plot(x=island.sales$benefaction, y=island.sales$capital, xlab="benefaction", ylab="capital")

スクリーンショット 2016-12-23 20.17.05.png

ついでなので回帰直線も入れてみましょう。

# 単回帰分析
> sales_cb.lm <- lm(island.sales$capital ~ island.sales$benefaction) 

# 回帰直線をplotに追加
> abline(sales_cb.lm)

スクリーンショット 2016-12-23 22.01.54.png

当然ですが、散布図をみていると資金投入が増えれば募金も増えているようです。当然ですが(笑)

それを裏付けるために募金額と資金投入額の相関関係を出します。
1=100%の相関で、90%以上で非常に強い相関と言われます。
今回は0.92なので、資金投入すればするほど募金してもらえるのは事実ということが言えます。

> cor(island.sales)
            benefaction    capital      sales
benefaction   1.0000000  0.9261008 -0.8093403
capital       0.9261008  1.0000000 -0.9711201
sales        -0.8093403 -0.9711201  1.0000000

売上を伸ばすために

さて、上の相関関係をよく見てください。ここで問題が発生しています。
そう、「売上」です。
募金額と売上は-0.8の負の相関。つまり募金が増えれば増えるほど、売上は減っているではありませんか!!!(ええーっ)

資金投入をすれば募金は増える。
でも、資金投入が増えれば売上からマイナスになる。
このルールのために、売上を伸ばすということは非常にハードルの高いものになっていました。

では、「売上を伸ばす」にはどうしたら良かったのでしょうか。

結論から言うと、ここから先はあまり有用なデータが取れなかったですが、やったことを一通り述べておきます。

重回帰分析

まず、売上の要因を調べようとしました。
ただ、売上自体が募金額と資金から算出されているものなので、そこに相関があるのは当たり前で、予想通り単独の結果は取れませんでした。

> sales.lm <- lm(island.sales$sales ~ island.sales$benefaction + island.sales$capital) 
> summary(sales.lm)

Call:
lm(formula = island.sales$sales ~ island.sales$benefaction + 
    island.sales$capital)

Residuals:
         1          2          3          4          5 
 6.586e-13 -5.756e-13  7.397e-13  7.034e-13 -1.526e-12 

Coefficients:
                           Estimate Std. Error    t value Pr(>|t|)    
(Intercept)               8.135e-13  9.304e-13  8.740e-01    0.474    
island.sales$benefaction  1.000e+00  3.939e-16  2.539e+15   <2e-16 ***
island.sales$capital     -1.000e+00  1.600e-16 -6.249e+15   <2e-16 ***
---
Signif. codes:  0***0.001**0.01*0.05.0.1 ‘ ’ 1

Residual standard error: 1.438e-12 on 2 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 5.661e+31 on 2 and 2 DF,  p-value: < 2.2e-16

Multiple R-squaredが1になっている -> 相関が強すぎる

レシートから購入したものを計測

買ったものとその個数・種別、それがどれくらい売れたかを測ろうとしました。
このあたりのデータを取るために、各島の人にレシートを残しておいてもらうようお願いしていたので、
レシートから購入したもの、各島の余りから何が売れたかはある程度割り出せたのですが、
購入されたものが個包装ではなくファミリーパックタイプのものが多く、結局いくつ内包されているうちのいくつが余っているかがわからず、これは分析を断念しました。

スクリーンショット 2016-12-23 22.54.18.png

考察(仮説)

そもそも論ですが、募金制度はお菓子を食べる人の善意であって利益を求めるものではない(買った額より高く売るということは基本的にない)ので、「売上」を追求するには非常に厳しいやり方だったのです。
お菓子の島バトルを始める前に行っていた募金制度では、買った額が補填できて、ちょっとプラスになるくらいが運営をするのにちょうど良かったんじゃないなかと思いました。

今回の各島の状況を見ていると、
最初に莫大な資金を注ぎ込んでお菓子を用意したチョコレー諸島やフルーツタル島は苦戦を強いられていました。
ただ、やりくり上手な島もあって、グラニュー島はそこそこ売りながらそこそこ募金してもらうということに成功していました。

仮説ですが、ある一定のラインを超えて資金投入をすると、その分がマイナスに反映されてしまうようなので、募金額の推移を見ながら必要なだけちょっとずつお菓子を補充するのが一番ベストな方法だったのではと推測しています。
また、11月下旬から準備をしてまだ1ヶ月弱の推移なので、もう少し期間が長けえれば運用も回ってくるはず。
最初に大量の資金投入をした島は後は回収のみなので、最終計測では募金が増えて売上が上昇していそうです。

まとめ

資金投入額を引き算しないと、権力者(お金がある人)のいる島が勝ってしまうなーと思っていろいろ考えてルールを設計しましたが、今回はそれが裏目に出てしまう結果となりました。
次への反省点としては、ある程度のシュミレーションは必要だなと感じました。

バトルとしては想定していない展開となってしまいましたが、
チュッパチャップスタワーが設置されたり、ハーゲンダッツのタイムセールが実施されたり、するめ・ブタメン・ウコンの力が陳列されたり・・・とそれなりに盛り上がったしみんなにも楽しんで取り組んでもらえたようで、なにはともあれ、良かったです。
エンジニアたるもの、 業務中の糖分補給は大事ですね。

部のみんなが島の名前を覚えて(きっと)愛着を持ってくれた(であろう)ことも嬉しく思います。
あと副産物として、これからの寒い季節に備えてこの1ヶ月で脂肪を蓄えることができた人も多かったようです。

風邪に気をつけて2017年も頑張りましょう!