1  第1回 売上をまとめた表をつくる

1.1 はじめに

第1回の内容は,POSデータを集約して,売上金額や売上個数の合計を計算し,販売状況の特徴を把握しやすい図や表を作成することです。

1.2 この章で使うファイルとパッケージ

ここで用いるデータが記録されているファイルは,Microsoft社のExcelのファイルです。 最近のMS Excelで作成されたファイルは拡張子に.xlsxがついています。 第1回の内容で扱うファイルは、

拡張子(extension)は,ファイル名の最後についている.xlsx.csvなどの文字列のことで,ファイルの種類を示しています。Windowsではデフォルトで拡張子が表示されない設定になっているかもしれないので,必ず拡張子を表示させる設定にしておいてください。.exeファイルを知らずに実行すると,ウイルスに感染する可能性があるので,拡張子を表示させることはセキュリティ上も重要です。

  • chp1.xlsx

という名前のファイルです。 このファイルは,Rの作業ディレクトリ(working directory)の中にあるdataフォルダに保存しておきます。

作業ディレクトリ(working directory)は,Rがファイルを読み込むときの基準となるフォルダのことです。Rを起動したときに,デフォルトで設定されているフォルダが作業ディレクトリになります。作業ディレクトリはgetwd()関数で確認できます。作業ディレクトリを変更するには,setwd()関数を使います。

Rの機能を拡張するために,ここでは以下のパッケージを用います。

  • tidyverse : データの読み込み,加工,可視化に使うパッケージ
  • readxl : Excelファイルを読み込むためのパッケージ

通常,Rではinstall.packages()関数を使ってパッケージをインストールし,library()で読み出しますが,ここではpacmanパッケージを使って一括でインストール・読み込みを行います。

pacmanパッケージを使うために,以下のコードを実行してください。

install.packages("pacman") # 最初の1回だけ実行

pacmanパッケージには便利な関数がいろいろありますが,ここではp_load()関数を使って複数のパッケージを一括で読み込みます。まだインストールされていないパッケージがあれば,自動でインストールされます。 便利なパッケージをいろいろ読み込んでおきましょう。

pacman::p_load(tidyverse, readxl, ggthemes, gt, gtExtras)
  • ggtheme : グラフのテーマを変更するためのパッケージ
  • gt : 表を作成するためのパッケージ
  • gtExtras : gtパッケージの拡張機能を提供するパッケージ

pacman::p_load()のように,「パッケージ名::関数名」という書き方で,パッケージ名を指定して関数を使うと,p_load()関数がpacmanパッケージの関数であることが分かりやすいので,似たような名前の関数があるときは,パッケージ名をつけて使うといいでしょう。 たとえば,dplyr::select()関数やreadxl::read_excel()関数です。

うえでも説明したとおり、今後分析に使う予定のファイルはすべて作業ディレクトリのdataフォルダにいれてある、と想定したソースコードを作成しているので、もしdataフォルダではない場所にファイルを保存している場合は、data/の部分を適宜変更してください。

Rは作業ディレクトリとなっているフォルダを軸にしてファイルを読み込むため,ファイルの場所に注意してください。 ここでは作業ディレクトリの中にdataフォルダを作り,そこにchp1.xlsxを保存してあるので,data/chp1.xlsxと指定することでファイルにアクセスしています。

1.3 Rの準備

  • Rをインストールしておきましょう。
  • RStudioかVS Codeをインストールしておきましょう。
  • Rのパッケージtidyverseをインストールしておきましょう。
  • 作業ディレクトリを設定しておきましょう。

これらの内容が分からない場合は,R入門の資料や本を参照してください。

1.4 データの読み込み

まずはreadxlパッケージを使ってデータchp1.xlsxを読み込んでみましょう。 このExcelファイルのシートの一覧を表示してみます。

readxl::excel_sheets("data/chp1.xlsx")
[1] "いつものPOSデータ"     "ピボットテーブル"      "表1-2・図1-19"        
[4] "表1-4・図1-28・図1-29" "表1-5・図1-32"         "表1-6"                
[7] "図1-38"               

excel_sheets()関数はデフォルトで1番目のシートを読み込みます。 「いつものPOSデータ」を読み込みたいので,特に指定せずにread_excel()関数を使って読み込みます。

df <- readxl::read_excel("data/chp1.xlsx")
head(df) # 戦闘6行を表示
Warning in attr(x, "align"): 'xfun::attr()' は廃止予定です
'xfun::attr2()' を代わりに使って下さい
help("Deprecated") を見て下さい
レシート番号 日付 曜日 時間 性別 年代 メーカー 商品名 単価 個数 金額
R000001 2023-01-02 10 女性 30代 競合A おいしい緑茶 160 2 320
R000001 2023-01-02 10 女性 30代 競合B 静岡の緑茶 170 2 340
R000002 2023-01-02 10 男性 60歳以上 競合A おいしい濃茶 160 2 320
R000002 2023-01-02 10 男性 60歳以上 競合B 静岡の緑茶 170 4 680
R000003 2023-01-02 10 男性 50代 競合C ほうじ茶 140 1 140
R000004 2023-01-02 10 女性 50代 競合D ウーロン茶 140 3 420

どんな変数があるのか確認するにはnames()関数を使います。

names(df)
 [1] "レシート番号" "日付"         "曜日"         "時間"         "性別"        
 [6] "年代"         "メーカー"     "商品名"       "単価"         "個数"        
[11] "金額"        

1.5 データの属性を確認する。

データの属性や型を確認するにはstr()関数を使います。

str(df)
tibble [374,090 × 11] (S3: tbl_df/tbl/data.frame)
 $ レシート番号: chr [1:374090] "R000001" "R000001" "R000002" "R000002" ...
 $ 日付        : POSIXct[1:374090], format: "2023-01-02" "2023-01-02" ...
 $ 曜日        : chr [1:374090] "月" "月" "月" "月" ...
 $ 時間        : num [1:374090] 10 10 10 10 10 10 10 10 10 10 ...
 $ 性別        : chr [1:374090] "女性" "女性" "男性" "男性" ...
 $ 年代        : chr [1:374090] "30代" "30代" "60歳以上" "60歳以上" ...
 $ メーカー    : chr [1:374090] "競合A" "競合B" "競合A" "競合B" ...
 $ 商品名      : chr [1:374090] "おいしい緑茶" "静岡の緑茶" "おいしい濃茶" "静岡の緑茶" ...
 $ 単価        : num [1:374090] 160 170 160 170 140 140 160 150 150 160 ...
 $ 個数        : num [1:374090] 2 2 2 4 1 3 1 2 3 4 ...
 $ 金額        : num [1:374090] 320 340 320 680 140 420 160 300 450 640 ...

dplyr::glimpse()関数を使うと,データの概要をより見やすく表示できます。

dplyr::glimpse(df)
Rows: 374,090
Columns: 11
$ レシート番号 <chr> "R000001", "R000001", "R000002", "R000002", "R000003", "R…
$ 日付         <dttm> 2023-01-02, 2023-01-02, 2023-01-02, 2023-01-02, 2023-01-…
$ 曜日         <chr> "月", "月", "月", "月", "月", "月", "月", "月", "月", "月", "月", "月…
$ 時間         <dbl> 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1…
$ 性別         <chr> "女性", "女性", "男性", "男性", "男性", "女性", "女性", "女性", "女性", "男性…
$ 年代         <chr> "30代", "30代", "60歳以上", "60歳以上", "50代", "50代", "50代", "50代…
$ メーカー     <chr> "競合A", "競合B", "競合A", "競合B", "競合C", "競合D", "競合A", "自社", "自…
$ 商品名       <chr> "おいしい緑茶", "静岡の緑茶", "おいしい濃茶", "静岡の緑茶", "ほうじ茶", "ウーロン茶", "お…
$ 単価         <dbl> 160, 170, 160, 170, 140, 140, 160, 150, 150, 160, 160, 17…
$ 個数         <dbl> 2, 2, 2, 4, 1, 3, 1, 2, 3, 4, 1, 2, 2, 1, 1, 2, 1, 2, 3, …
$ 金額         <dbl> 320, 340, 320, 680, 140, 420, 160, 300, 450, 640, 160, 34…

この表の上部をみると、このデータには変数が11個,観測値が374,090個あることが分かります。 また,変数名の横に<chr><dbl>といった文字が表示されていますが,これは変数の型を示しています。 <chr>は文字列型,<dbl>は数値型,<dttm>は日付型を示しています。

文字型,数値型,日付型以外にも,

  • <fct>: 因子型
  • <int>: 整数型
  • <lgl>: 論理型

などがあります。

1.6 データの概要を確認する

データの属性を確認するために,summary()関数を使ってみましょう。 基本関数summary()は,データの記述統計量などを返してくれる関数です。

 レシート番号            日付                            曜日          
 Length:374090      Min.   :2023-01-02 00:00:00.00   Length:374090     
 Class :character   1st Qu.:2023-05-09 00:00:00.00   Class :character  
 Mode  :character   Median :2023-07-28 00:00:00.00   Mode  :character  
                    Mean   :2023-07-16 10:09:45.75                     
                    3rd Qu.:2023-09-23 00:00:00.00                     
                    Max.   :2023-12-31 00:00:00.00                     
      時間           性別               年代             メーカー        
 Min.   :10.00   Length:374090      Length:374090      Length:374090     
 1st Qu.:13.00   Class :character   Class :character   Class :character  
 Median :16.00   Mode  :character   Mode  :character   Mode  :character  
 Mean   :15.57                                                           
 3rd Qu.:18.00                                                           
 Max.   :21.00                                                           
    商品名               単価            個数             金額       
 Length:374090      Min.   :140.0   Min.   : 1.000   Min.   : 140.0  
 Class :character   1st Qu.:150.0   1st Qu.: 1.000   1st Qu.: 160.0  
 Mode  :character   Median :160.0   Median : 2.000   Median : 280.0  
                    Mean   :154.5   Mean   : 1.783   Mean   : 275.7  
                    3rd Qu.:160.0   3rd Qu.: 2.000   3rd Qu.: 320.0  
                    Max.   :170.0   Max.   :14.000   Max.   :2100.0  

この表より,

  • 日付は2023年1月2日から2023年12月31日まで
  • 時間は10:00から21:00まで
  • 単価は数値で,140〜170
  • 個数は数値で,1〜14
  • 金額は数値で,140〜2100

となっていることがわかります。 また文字型となっている曜日性別年代メーカー商品名はデータの個数としてLength:が出力されていることがわかります。 文字列のsummary()を出力しても意味がないので,文字型の変数を除外して,数値型の変数だけを表示するには,select()関数とwhere()関数を使い, is.double関数を使って数値型の変数だけを選択します。

df |>
  select(where(is.double)) |>
  summary()
      日付                             時間            単価      
 Min.   :2023-01-02 00:00:00.00   Min.   :10.00   Min.   :140.0  
 1st Qu.:2023-05-09 00:00:00.00   1st Qu.:13.00   1st Qu.:150.0  
 Median :2023-07-28 00:00:00.00   Median :16.00   Median :160.0  
 Mean   :2023-07-16 10:09:45.75   Mean   :15.57   Mean   :154.5  
 3rd Qu.:2023-09-23 00:00:00.00   3rd Qu.:18.00   3rd Qu.:160.0  
 Max.   :2023-12-31 00:00:00.00   Max.   :21.00   Max.   :170.0  
      個数             金額       
 Min.   : 1.000   Min.   : 140.0  
 1st Qu.: 1.000   1st Qu.: 160.0  
 Median : 2.000   Median : 280.0  
 Mean   : 1.783   Mean   : 275.7  
 3rd Qu.: 2.000   3rd Qu.: 320.0  
 Max.   :14.000   Max.   :2100.0  

is.double()関数は,引数の型が数値型かどうかを判定する関数で,数値型の場合はTRUEを返し,そうでない場合はFALSEを返します。このように,is.型名()関数は,型を判定する関数として使われます。 条件を満たす変数だけを選択するdplyr::select()関数と,dplyr::where()関数を使うことで変数の型を指定して変数を抽出できます。

1.7 因子型

これらの文字型変数曜日性別年代メーカー商品名は,どのカテゴリーに属しているかを表しているカテゴリカルデータであるため, 文字型から因子型(factor)に変換しておきましょう。 変数を因子型に変更するには,facor()関数やas.factor()関数を使います。 ここでは,曜日に順番があるため,levelsオプションとorderedオプションで曜日の種類と順番を指定しています。

df <- df %>%
  mutate(曜日 = factor(曜日, levels = c("月", "火", "水", "木", "金", "土", "日"), ordered = TRUE),
         性別 = as.factor(性別),
         年代 = as.factor(年代),
         メーカー = as.factor(メーカー),
         商品名 = as.factor(商品名))

変数の型を変更したので,もう一度,summary()関数を使ってデータを確認してみましょう。

 レシート番号            日付                        曜日            時間      
 Length:374090      Min.   :2023-01-02 00:00:00.00   月:36468   Min.   :10.00  
 Class :character   1st Qu.:2023-05-09 00:00:00.00   火:44573   1st Qu.:13.00  
 Mode  :character   Median :2023-07-28 00:00:00.00   水:52418   Median :16.00  
                    Mean   :2023-07-16 10:09:45.75   木:37703   Mean   :15.57  
                    3rd Qu.:2023-09-23 00:00:00.00   金:66894   3rd Qu.:18.00  
                    Max.   :2023-12-31 00:00:00.00   土:74754   Max.   :21.00  
                                                     日:61280                  
   性別              年代        メーカー               商品名     
 女性:274659   20歳未満:19102   競合A:144742   ウーロン茶  :31905  
 男性: 99431   20代    :49716   競合B: 46516   おいしい濃茶:59910  
               30代    :81065   競合C: 39190   おいしい緑茶:84832  
               40代    :74773   競合D: 31905   ほうじ茶    :39190  
               50代    :93194   自社 :111737   静岡の緑茶  :46516  
               60歳以上:56240                  濃い茶      :45982  
                                               緑茶        :65755  
      単価            個数             金額       
 Min.   :140.0   Min.   : 1.000   Min.   : 140.0  
 1st Qu.:150.0   1st Qu.: 1.000   1st Qu.: 160.0  
 Median :160.0   Median : 2.000   Median : 280.0  
 Mean   :154.5   Mean   : 1.783   Mean   : 275.7  
 3rd Qu.:160.0   3rd Qu.: 2.000   3rd Qu.: 320.0  
 Max.   :170.0   Max.   :14.000   Max.   :2100.0  
                                                  

すると,曜日性別年代メーカー商品名がカテゴリー変数として認識され,カテゴリーごとの個数が表示されています。

1.8 条件によるデータの抽出

メーカー変数が自社の場合だけを抽出するには,dplyr::filter()関数を使います。 filter()関数は,引数にメーカー == "自社という条件を指定することで,条件に合致するデータだけを抽出します。

df |>
  dplyr::filter(メーカー == "自社") |>
  head()
Warning in attr(x, "align"): 'xfun::attr()' は廃止予定です
'xfun::attr2()' を代わりに使って下さい
help("Deprecated") を見て下さい
レシート番号 日付 曜日 時間 性別 年代 メーカー 商品名 単価 個数 金額
R000005 2023-01-02 10 女性 50代 自社 濃い茶 150 2 300
R000005 2023-01-02 10 女性 50代 自社 緑茶 150 3 450
R000010 2023-01-02 10 女性 50代 自社 濃い茶 150 2 300
R000010 2023-01-02 10 女性 50代 自社 緑茶 150 1 150
R000011 2023-01-02 10 男性 20代 自社 緑茶 150 1 150
R000012 2023-01-02 10 女性 20代 自社 緑茶 150 1 150

1.9 基礎集計でデータの傾向をチェック

メーカーごとの売上金額合計を示す表を作成してみましょう。 Excelでピボットテーブルを使う手続が教科書で解説されていますが,Rだとdplyrパッケージを使って簡単にできます。

df_maker_sales <- df |>
  dplyr::group_by(メーカー) |>
  dplyr::summarise(売上金額合計 = sum(金額))
df_maker_sales
Warning in attr(x, "align"): 'xfun::attr()' は廃止予定です
'xfun::attr2()' を代わりに使って下さい
help("Deprecated") を見て下さい
メーカー 売上金額合計
競合A 42695520
競合B 13537440
競合C 9289700
競合D 7486080
自社 30126150

これだけです。 キレイな表にするなら,gt()関数とgtExtraパッケージを使うといいでしょう。

df_maker_sales |>
  gt() |>
  fmt_number(columns = 2:2, decimals = 0) |>
  tab_header(title = "表1-2 メーカーごとの売上金額") |>
  gt_theme_pff() |> # テーマを適用
  as_raw_html()
表1-2 メーカーごとの売上金額
メーカー 売上金額合計
競合A 42,695,520
競合B 13,537,440
競合C 9,289,700
競合D 7,486,080
自社 30,126,150

次に,各メーカーのどの商品が,平均何円で売られているのか,を調べてみましょう。 group_by()関数の引数に,メーカー商品名を指定して,summarise()関数でグループごとの平均単価を計算し, arrange()関数でメーカーと平均単価でソートします。desc()関数は降順にソートするための関数です。

df_maker_item <- df |>
  group_by(メーカー, 商品名) |> # メーカーと商品名でグループ化
  summarise(平均単価 = mean(単価)) |> # 平均単価を計算
  arrange(メーカー, desc(平均単価)) |># メーカーと平均単価でソート
  ungroup()
`summarise()` has grouped output by 'メーカー'. You can override using the
`.groups` argument.
df_maker_item |>
  gt() |>
  fmt_number(columns = 3:3, decimals = 0) |>
  tab_header(title = "表1−3 商品ごとの単価") |>
  gt_theme_pff() |> # テーマを適用
  as_raw_html()
表1−3 商品ごとの単価
メーカー 商品名 平均単価
競合A おいしい濃茶 160
競合A おいしい緑茶 160
競合B 静岡の緑茶 170
競合C ほうじ茶 140
競合D ウーロン茶 140
自社 濃い茶 150
自社 緑茶 150

1.10 資料作成に必要なデータを取り出す

データ全体における売上金額と売上個数を計算して,各月と各時間帯にの売上金額を計算してみる。

# 全体の売上金額と売上個数
df |>
  summarise(
    売上金額合計 = sum(金額),
    売上個数合計 = sum(個数)
    )
Warning in attr(x, "align"): 'xfun::attr()' は廃止予定です
'xfun::attr2()' を代わりに使って下さい
help("Deprecated") を見て下さい
売上金額合計 売上個数合計
103134890 667147

自社製品ごとの個数と金額を計算してみましょう。

df_jisha_total <- df |>
  filter(メーカー == "自社") |> # 自社製品だけを抽出
  group_by(商品名) |>
  summarise(
    売上金額合計 = sum(金額),
    売上個数合計 = sum(個数)
    ) |>
  arrange(desc(売上金額合計))
df_jisha_total
Warning in attr(x, "align"): 'xfun::attr()' は廃止予定です
'xfun::attr2()' を代わりに使って下さい
help("Deprecated") を見て下さい
商品名 売上金額合計 売上個数合計
緑茶 18057150 120381
濃い茶 12069000 80460

これで自社の製品ごとの売上金額と売上個数の合計が計算されました。 ここで注意しないといけないことは,group_by()関数とsummarise()関数を使った場合,グループごとに1つの統計量を返すため,上のコードだと, 自社の2商品ごとの売上金額と売上個数の合計が出力され,2行2列のデータフレームが返されていることが分かります。

次に,各月ごとの売上金額を計算してみましょう。 日付変数の型を確認します。

class(df$日付)
[1] "POSIXct" "POSIXt" 

POSIXct POSIXt という日付型のデータです。 この変数日付から月を取り出すには,lubridateパッケージを使います。 日付データは2023-05-14 UTCといった形式で格納されているため,lubridate::month()関数を使って月を取り出します。

df_month_sales <- df |>
  filter(メーカー == "自社") |>
  mutate(= lubridate::month(日付, label = TRUE)) |>
  group_by() |> # 月ごとにグループ化
  summarise(売上金額合計 = sum(金額)) |>
  arrange() |>
  ungroup()

df_month_sales |>
  gt() |>
  fmt_number(columns = 2:2, decimals = 0) |>
  tab_header(title = "表1−5 自社商品の月ごとの売上金額") |>
  gt_theme_pff() |> # テーマを適用
  tab_options(
    heading.title.font.size = "small",
    table.font.size = "large",
    table.width = pct(60)
    )
表1−5 自社商品の月ごとの売上金額
売上金額合計
1 1,577,250
2 1,317,900
3 1,809,300
4 2,238,750
5 2,506,050
6 2,288,550
7 3,844,350
8 4,231,950
9 3,599,550
10 2,888,250
11 2,140,800
12 1,683,450

同じように各時間帯ごとの売上金額を計算してみましょう。

df_time_sales <- df |>
  filter(メーカー == "自社") |>
  group_by(時間) |>
  summarise(売上金額合計 = sum(金額)) |>
  arrange(時間) |>
  ungroup()

df_time_sales |>
  gt() |>
  fmt_number(columns = 2:2, decimals = 0) |>
  gt_theme_pff() |> # テーマを適用
  tab_header(title = "表1−6 自社商品の時間帯別売上高") |>
  tab_options(
        heading.title.font.size = "small",
        table.font.size = "large",
        table.width = pct(60)
        )
表1−6 自社商品の時間帯別売上高
時間 売上金額合計
10 1,506,600
11 2,070,750
12 2,942,400
13 2,729,550
14 2,108,700
15 2,740,050
16 3,033,150
17 3,617,700
18 3,038,550
19 2,710,950
20 2,124,900
21 1,502,850

1.11 集計結果をグラフで可視化

可視化はRの得意分野です。 ggplot2パッケージを使って,いろんなグラフで表示してみましょう。

ggplot2パッケージで日本語を表示させるためには,一手間必要になります。 しかもMacOSとWindowsでやり方が異なるので,注意してください。 松浦の環境はMacOSであるため,ヒラギノフォントを指定してます。 ついでに,カラーパレットもユニバーサルデザインに配慮したscale_fill_tableau(name = "Tableau 20")を指定してます。

メーカー別の売上合計金額を棒グラフにします。

df_maker_sales |>
  ggplot() + aes(x = メーカー, y = 売上金額合計, fill = メーカー) +
  geom_col() + theme_bw(base_family = "Noto San JP") +
  scale_fill_tableau(name = "Tableau 20") # Tableau 20 パレットを適用

月別売上高を折れ線グラフにします。

df_month_sales |>
  ggplot() + aes(x = , y = 売上金額合計, group = 1) +
  geom_line() + geom_point() +
  theme_bw(base_family = "HiraKakuPro-W3")

夏に売上高がピークを迎えていることが分かります。

時間帯別売上高を棒グラフにします。

df_time_sales |>
  ggplot() +
  aes(x = 時間, y = 売上金額合計, fill = factor(時間, levels = rev(unique(時間)))) + # 時間の順序を逆にする
  geom_col() + theme_bw(base_family = "HiraKakuPro-W3") + # テーマとフォント
  guides(fill = guide_legend(title = "時間帯")) +
  scale_fill_viridis_d(direction = 1) # Viridis パレットを逆順に適用

12時ころと17時ころに売上高が大きくなっているので,昼食・夕食の時間帯に売上が伸びていることが分かります。

さらに,月ごと,時間ごとの棒グラフを重ねて表示してみましょう。

df_month_time_sales <- df |>
  filter(メーカー == "自社") |>
  mutate(= lubridate::month(日付, label = TRUE),
         時間 = as.factor(時間)) |>
  group_by(, 時間) |>
  summarise(売上金額合計 = sum(金額)) |>
  arrange(, 時間)
`summarise()` has grouped output by '月'. You can override using the `.groups`
argument.
df_month_time_sales |>
  ggplot() + aes(x = , y = 売上金額合計, fill = 時間) +
  geom_col(position = "dodge") + theme_bw(base_family = "HiraKakuPro-W3") +
  guides(fill = guide_legend(title = "時間帯")) +
  scale_fill_viridis_d(direction = -1)

昼食時と夕食前に売上が伸びる傾向は1月から12月まで観察されていますが,その差は夏が非常に多く,冬には昼食時と夕食前とそれ以外の売上の差が小さくなっていることが分かります。

これをアニメーションにしてみましょう。 Rにはggplot2パッケージで作ったグラフをアニメーションにするgganimateパッケージがあります。 ここでは,transition_states()関数とenter_fade()関数,exit_fade()関数を使って,時間帯ごとの売上高をアニメーションで表示してみます。

  • transition_states(): アニメーションの状態を指定します。
  • enter_fade(): アニメーションの開始時のエフェクトを指定します。
  • exit_fade(): アニメーションの終了時のエフェクトを指定します。
pacman::p_load(gganimate)
df_month_time_sales |>
  ggplot() +
  aes(x = , y = 売上金額合計, fill = 時間) +
  geom_col(position = "dodge") +
  theme_bw(base_family = "HiraKakuPro-W3") +
  guides(fill = guide_legend(title = "時間帯")) +
  scale_fill_viridis_d(direction = -1) +
  transition_states(時間, transition_length = 2, state_length = 1) +
  labs(
    title = "月ごとの時間帯別売上高: 時間帯 {closest_state} 時",
    x = "月",
    y = "売上金額合計"
  ) +
  enter_fade() +
  exit_fade()

同じように,月と時間を入れ替えてみましょう。

df_month_time_sales |>
  ggplot() +
  aes(x = 時間, y = 売上金額合計, fill = ) +
  geom_col(position = "dodge") +
  theme_bw(base_family = "HiraKakuPro-W3") +
  guides(fill = guide_legend(title = "月")) +
  scale_fill_viridis_d(direction = -1) +
  transition_states(, transition_length = 2, state_length = 1) +
  labs(
    title = "時間ごとの月別売上高:  {closest_state} 月",
    x = "時間",
    y = "売上金額合計"
  ) +
  enter_fade() +
  exit_fade()

テキストの気温と販売個数の散布図は,気温データがないため作れません。

1.12 提出用の資料を作成する。

テキストではMS Excelで作成した表を、MS Powerpointに貼り付けてスライド資料を作成するようになっていますが、 RとQuartoを使えば、データ分析と資料作成を同じ場所で行うことができます。