Technically Impossible

Lets look at the weak link in your statement. Anything "Technically Impossible" basically means we haven't figured out how yet.

Rの初歩 - 相関係数、データフレーム内の値を集計する。

先日に引き続き、相関係数に関する復習。今回は演習問題だけで、復習はない。とはいえ演習問題に対応しながら、次のことが気になった。データフレーム内の値を簡単に集計するには、どうすればよいのか?例えば次のような場合だ。

  • データフレーム中に顧客の年齢と買い上げ金額が記録されている。
  • 買い上げ金額を年代別(10代、20代、30代...)に集計したい。

日頃、得られたデータフレームを直接関数へ投入しているばかりなので、ほんの少しの手間が必要になると、途端に作業が止まってしまう。Excelならば簡単に対応できるのだが、データ件数が増えたときのことを考えると、ここでRでの対応方法を調べておくのが得策だろう。

今回は、まず演習問題をこなした上で、データフレーム内のデータを集計することを考えたい。

追記、2021年1月24日
データフレーム内の集計について、この投稿で紹介する方法以外に、Tidyverseの方法に則る方法が分かりやすく、効率的だ。Tidyverseについての投稿でも同様の話題に触れている。合わせて参照してほしい。
Rの初歩 - Tidyなやり方 Tidyverse - Technically Impossible

演習問題

github.com
与えられた資料は顧客の買い上げ金額一覧だ。顧客の年齢と買い上げ金額が記録されている。次の問いに対応せよ。

1) Get basic statistics for age and sales
2) Get distribution of ages
3) Get distribution of sales amount
4) Plot sales amount per age
5) Develop sale strategy based on data

まず与えられたExcelを読み込む。

library(readxl)
data <- read_excel("data.xlsx")

basic statisticsはsummary関数を利用する。関数のリファレンスは、エントリ末尾にまとめている。

> summary(data$Age)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  21.00   31.00   40.50   43.54   57.00   75.00 
> summary(data$Sales)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1154    1987    2472    4331    5247   13916 

年齢、買い上げ金額の分布をグラフ表示する。ここでは問5への展開も考慮して、ヒストグラムと箱ひげ図を確認しておく。

par(mfcol = c(2, 1))

を指定して、2つのグラフを一つの画像にまとめている。言い換えると、一列に2行表示している。
買い上げ金額の箱ひげ図で「range = 0」を指定しているのは、外れ値が検出されたからだ。実際には外れ値ではないため、ヒゲを伸ばしている。

par(mfcol = c(2, 1))
hist(data$Age)
boxplot(data$Age, horizontal = T)

par(mfcol = c(2, 1))
hist(data$Sales)
boxplot(data$Sales, horizontal = T, range = 0)

f:id:espio999:20190208000334p:plain
f:id:espio999:20190208000346p:plain
買い上げ金額と年齢をプロットし、相関係数を求める。

> plot(data$Age, data$Sales)
> cor(data$Age, data$Sales)
[1] 0.629401

f:id:espio999:20190208000409p:plain
ここまで対応したところで、得られた知見から営業戦略を考えるところなのだが...ここで冒頭の集計の話題に戻るのだ。

データフレーム内のデータ集計

ここまでで得られた知見をまとめると、

  • 顧客は40歳を境に、半分に分かれる。
  • 買い上げ金額は、約2500円以下のグループが半分、そこから5000円程度までが25%。それ以降のロングテールが25%。
  • 年齢と買い上げ金額に相関は見られるものの、プロットを見ると2極化が見える。
    • 50歳未満は4000円程度までの買い物が多い。
    • 50歳以上は1万円を超える買い物があるものの、年齢も金額も分散している。

これだけで考えると、50歳未満には高額の買い物につながる、50歳以上には買い物回数を増やす施策を検討したくなるところだ。ところで買い上げ金が最も多い領域というのはどこだろう?ここで買い上げ金額を年代で集計したくなるのだ。このような手順を考えた。

  1. 年齢を10で割り、整数商を求める。それを10倍した値でベクトルをつくる。
  2. 買い上げ金額を、1のベクトルに基づいて集計する。集計結果がデータフレームとして出力される。

ここまでを次のコードで表現できる。aggregate関数にsum関数を指定して集計している。引数にはベクトル、リストであることが求められるので、都度変換している。

range = (data$Age %/% 10) * 10
ret=aggregate(c(data$Sales), list(range), sum)

そして、この集計結果をグラフ表示したい。barplot関数で棒グラフとして表示するのだが、やはり引数の制約がある。ベクトルを引数とするため、対象データから新たなベクトルを作成する。

v = ret$x
names(v) = ret$Group.1
barplot(v)

f:id:espio999:20190208000753p:plain
グラフから、50代の売り上げが突出していることが分かる。2番手は30代、60代だ。突出している世代に特化した営業戦略、あるいは買い上げ金額の少ない世代にアピールする営業戦略など、問5に回答するための視野が広がった。

追記、2021年1月24日

データフレーム内の集計について、この投稿で紹介する方法以外に、Tidyverseの方法に則る方法が分かりやすく、効率的だ。Tidyverseについての投稿でも同様の話題に触れている。合わせて参照してほしい。
impsbl.hatenablog.jp