Analysis

Mixed beverage gross receipts analysis

The goal of this notebook is to analyze seasonal and monthly sales fluctuations in alcohol sales over the last five years (2019 through 2023) in Austin neighborhoods using the data I cleaned from the Texas Open Data Portal.

I will analyze how alcohol sales change through the year, how these changes correlate with seasonal factors and which neighborhoods are affected by these fluctuations. This analysis will also examine how major events throughout the years, like SXSW and ACL impact sales across neighborhoods. To further this analysis, I will break down sales by alcohol type and identify if any drive more revenue in different areas and seasons.

Goals

I will answer the following questions in this notebook:

  • Which months had the highest average total alcohol sales across Austin in the last five years?
  • How have total alcohol sales in Austin changed from 2019 to 2023?
  • Which type of alcohol drives the most revenue citywide, and does this vary by season?
  • Which neighborhoods have the highest and lowest average sales?
  • Which neighborhoods see the largest spikes in sales during ACL in October?
  • Which neighborhoods see the largest spikes in sales during SXSW in March?

Setup

library(tidyverse)
library(janitor)

Import

I am importing my cleaned data.

# Importing the clean data
mixedbev <- read_rds("data-processed/01-mixedbev.rds")

mixedbev |> glimpse()
Rows: 73,721
Columns: 28
$ taxpayer_number            <dbl> 32057827142, 32049953949, 32058372064, 3203…
$ taxpayer_name              <chr> "ROCKROSE RESTAURANT L.L.C. DBA MIA ITALIAN…
$ taxpayer_address           <chr> "11420 ROCK ROSE AVE STE 120", "PO BOX 6850…
$ taxpayer_city              <chr> "AUSTIN", "AUSTIN", "AUSTIN", "MANCHACA", "…
$ taxpayer_state             <chr> "TX", "TX", "TX", "TX", "TX", "TX", "TX", "…
$ taxpayer_county            <dbl> 227, 227, 227, 227, 227, 227, 227, 227, 227…
$ location_number            <dbl> 1, 1, 1, 3, 1, 1, 2, 1, 1, 2, 1, 1, 1, 294,…
$ location_name              <chr> "MIA ITALIAN TAPAS & BAR", "THE LODGE", "EL…
$ location_address           <chr> "11420 ROCK ROSE AVE UNIT 400", "411 E 6TH …
$ location_city              <chr> "AUSTIN", "AUSTIN", "AUSTIN", "AUSTIN", "AU…
$ location_state             <chr> "TX", "TX", "TX", "TX", "TX", "TX", "TX", "…
$ location_county            <dbl> 227, 227, 227, 227, 227, 227, 227, 227, 227…
$ inside_outside_city_limits <chr> "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y"…
$ tabc_permit_number         <chr> "MB927828", "MB848429", "MB630996", "MB1061…
$ liquor_receipts            <dbl> 22983, 151396, 3324, 12204, 57536, 31245, 5…
$ wine_receipts              <dbl> 14304, 128, 0, 3326, 1979, 572, 23573, 9, 3…
$ beer_receipts              <dbl> 3953, 24110, 3719, 1610, 36461, 33655, 1084…
$ cover_charge_receipts      <dbl> 0, 7219, 0, 0, 0, 0, 0, 7453, 0, 0, 0, 31, …
$ total_receipts             <dbl> 41240, 182853, 7043, 17140, 95976, 65472, 9…
$ responsibility_begin       <date> 2015-11-24, 2013-08-08, 2015-10-15, 2020-1…
$ responsibility_end         <date> NA, NA, NA, 2023-07-12, NA, NA, NA, NA, NA…
$ obligation_end             <date> 2021-06-30, 2023-06-30, 2019-08-31, 2022-0…
$ taxpayer_zip_code          <chr> "78758", "78768", "78704", "78652", "78701"…
$ location_zip_code          <chr> "78758", "78701", "78704", "78704", "78701"…
$ yr                         <dbl> 2021, 2023, 2019, 2022, 2019, 2019, 2019, 2…
$ mo                         <dbl> 6, 6, 8, 5, 8, 6, 5, 6, 1, 6, 10, 1, 6, 12,…
$ mo_label                   <ord> Jun, Jun, Aug, May, Aug, Jun, May, Jun, Jan…
$ mo_long                    <ord> June, June, August, May, August, June, May,…
mixedbev
# A tibble: 73,721 × 28
   taxpayer_number taxpayer_name   taxpayer_address taxpayer_city taxpayer_state
             <dbl> <chr>           <chr>            <chr>         <chr>         
 1     32057827142 ROCKROSE RESTA… 11420 ROCK ROSE… AUSTIN        TX            
 2     32049953949 KLODGE, INC.    PO BOX 685084    AUSTIN        TX            
 3     32058372064 EL BORREGO DE … 3900 S CONGRESS… AUSTIN        TX            
 4     32039907699 DESI & FRIENDS… 12700 ENCINO DR  MANCHACA      TX            
 5     32039685030 WL STAR BAR, L… 600 W 6TH ST     AUSTIN        TX            
 6     17427121425 CASINO EL CAMI… 517 E 6TH ST     AUSTIN        TX            
 7     32045024711 SWOON HOSPITAL… 2406 HOMEDALE C… AUSTIN        TX            
 8     32069216045 407 BARLIB LLC  PO BOX 685084    AUSTIN        TX            
 9     32055355815 SOUTH FIRST PI… 2901 S 1ST ST S… AUSTIN        TX            
10     32051844242 EATX COFFEE LLC 22601 STATE HIG… SPICEWOOD     TX            
# ℹ 73,711 more rows
# ℹ 23 more variables: taxpayer_county <dbl>, location_number <dbl>,
#   location_name <chr>, location_address <chr>, location_city <chr>,
#   location_state <chr>, location_county <dbl>,
#   inside_outside_city_limits <chr>, tabc_permit_number <chr>,
#   liquor_receipts <dbl>, wine_receipts <dbl>, beer_receipts <dbl>,
#   cover_charge_receipts <dbl>, total_receipts <dbl>, …

Average monthly sales

Which months had the highest average total alcohol sales across Austin in the last five years?

I am grouping the data by month (mo_label) and year (yr), then using summarise() to calculate the sum totals (mo_yr_receipts) for the mo/year first. Then, I get the mean of those by months (avg_mo_receipts) using summarise again. Finally, I am arranging the data by avg_mo_receipts in descending order so that the data is showing the months with the highest sales first.

# Average monthly total alcohol sales
average_monthly_receipts <- mixedbev |>
  group_by(mo_label, yr) |>
  summarise(mo_yr_receipts = sum(total_receipts)) |>
  group_by(mo_label) |>
  summarise(avg_mo_receipts = mean(mo_yr_receipts)) |>
  arrange(desc(avg_mo_receipts))
`summarise()` has grouped output by 'mo_label'. You can override using the
`.groups` argument.
average_monthly_receipts
# A tibble: 12 × 2
   mo_label avg_mo_receipts
   <ord>              <dbl>
 1 Oct            88881854.
 2 Mar            81599109.
 3 Sep            80173455.
 4 May            77233152.
 5 Dec            76094336 
 6 Nov            74253798 
 7 Apr            73077065.
 8 Jun            72817260.
 9 Jul            71377155.
10 Aug            69742374.
11 Feb            67537899.
12 Jan            62923171.

Data takeaway: On average, Austin sees the highest average alcohol sales in October. The city sees the average lowest alcohol sales in January.

Visualization: Monthly sales

I will use ggplot to create a bar chart from my data that show the average monthly alcohol sales in Austin. I will be using this chart for my summary.

# Creating a vertical column chart for average monthly total alcohol sales
average_monthly_receipts |> 
  ggplot(aes(x = mo_label, y = avg_mo_receipts)) +
  geom_col(fill = "steelblue") +
  scale_y_continuous(
    breaks = c(20000000, 40000000, 60000000, 80000000, 100000000), 
    labels = c("20M", "40M", "60M", "80M", "100M")
  ) +
  labs(
    title = "Austin sells the most alcoholic beverages in October",
    subtitle = str_wrap("On average, Austin sees the highest average alcohol sales in October. The city sees the average lowest alcohol sales in January."),
    caption = "By Gabriella Gonzales. Source: Texas Comptroller of Public Accounts",
    x = "Month",
    y = "Average Total Receipts"
  )

ggsave("figures/average_monthly_sales.png")
Saving 7 x 5 in image

Sales by alcohol type

Which type of alcohol drives the most revenue citywide, and does this vary by season?

I am grouping the data by month (mo_label) and year (yr), then using summarise() to calculate the sum totals for the mo/year for each alcohol type. Then, I get the mean of those by month using summarise again. Finally, I am arranging the data by mo_label to display the results in chronological order by month.

# Average monthly sales by alcohol type
avg_by_type <- mixedbev |>
  group_by(mo_label, yr) |>
  summarise(
    mo_yr_liquor = sum(liquor_receipts),
    mo_yr_wine = sum(wine_receipts),
    mo_yr_beer = sum(beer_receipts),
    ) |>
  group_by(mo_label) |>
  summarise(
    avg_mo_liquor = mean(mo_yr_liquor),
    avg_mo_wine = mean(mo_yr_wine),
    avg_mo_beer = mean(mo_yr_beer),
    ) |>
  arrange(mo_label)
`summarise()` has grouped output by 'mo_label'. You can override using the
`.groups` argument.
avg_by_type
# A tibble: 12 × 4
   mo_label avg_mo_liquor avg_mo_wine avg_mo_beer
   <ord>            <dbl>       <dbl>       <dbl>
 1 Jan          38113734.    9733503.   14838484.
 2 Feb          41016909.   10782751    15499683.
 3 Mar          50656142    11348670.   19289354.
 4 Apr          45690418    10338782.   16755994 
 5 May          48809529.   10731652.   17410794.
 6 Jun          45987092.    9621532.   16948460.
 7 Jul          45758129.    9023091.   16366756.
 8 Aug          43881150.    9363101.   16204009.
 9 Sep          50247311.   10684106    18884303.
10 Oct          53847884.   13013958    21655787.
11 Nov          44892646.   12002320.   17036328.
12 Dec          47126036.   12383023.   16236911.

Data takeaway: Liquor drives the most revenue in Austin year-round, with spikes during March and October which host SXSW and ACL, respectively.

Visualization: Sales by alcohol type

I will pivot longer so that I can plot the data into a line chart.

# Pivot longer
avg_by_type_long <- avg_by_type |>
  pivot_longer(
    cols = c(avg_mo_liquor, 
             avg_mo_wine, 
             avg_mo_beer),
    names_to = "alcohol_type",
    values_to = "average_receipts"
    )

avg_by_type_long
# A tibble: 36 × 3
   mo_label alcohol_type  average_receipts
   <ord>    <chr>                    <dbl>
 1 Jan      avg_mo_liquor        38113734.
 2 Jan      avg_mo_wine           9733503.
 3 Jan      avg_mo_beer          14838484.
 4 Feb      avg_mo_liquor        41016909.
 5 Feb      avg_mo_wine          10782751 
 6 Feb      avg_mo_beer          15499683.
 7 Mar      avg_mo_liquor        50656142 
 8 Mar      avg_mo_wine          11348670.
 9 Mar      avg_mo_beer          19289354.
10 Apr      avg_mo_liquor        45690418 
# ℹ 26 more rows

Now, I will create my line chart using ggplot. I will be using this chart for my summary.

# Creating the line chart
avg_by_type_long |>
  ggplot(aes(x = mo_label,
             y = average_receipts,
             group = alcohol_type)) +
  geom_line(aes(color = alcohol_type)) +
  geom_point(aes(color = alcohol_type)) +
  scale_y_continuous(
    breaks = c(10000000, 20000000, 30000000, 40000000, 50000000), 
    labels = c("10M", "20M", "30M", "40M", "50M")
  ) +
  labs(
    title = "Liquor drives the most revenue in Austin year-round",
    subtitle = str_wrap("Liquor drives the most revenue in Austin year-round, with spikes during March and October which host SXSW and ACL, respectively."),
    caption = "By Gabriella Gonzales. Source: Texas Comptroller of Public Accounts",
    x = "Month",
    y = "Average Receipts",
    color = "Alcohol Type"
    )  +
  scale_color_manual(
    values = c("avg_mo_liquor" = "skyblue", 
               "avg_mo_beer" = "springgreen", 
               "avg_mo_wine" = "indianred"),
    labels = c("Average beer receipts", "Average liquor receipts", "Average wine receipts"))

ggsave("figures/alcohol_types.png")
Saving 7 x 5 in image

Sales by ZIP code

Which neighborhoods have the highest average sales?

I am grouping the data by month (mo_label) and year (yr), then using summarise() to calculate the sum totals (zip_total_receipts) for the mo/year first. Then, I get the mean of those by months (avg_zip_sales) using summarise again. Finally, I am arranging the data by avg_zip_sales in descending order so that the data is showing the ZIP codes with the highest average sales first.

# Calculate average sales by ZIP code
avg_sales_by_zip <- mixedbev |>
  group_by(location_zip_code, yr, mo_label) |>
  summarise(zip_total_receipts = sum(total_receipts)) |>
  group_by(location_zip_code) |>
  summarise(avg_zip_sales = mean(zip_total_receipts)) |>
  arrange(desc(avg_zip_sales))
`summarise()` has grouped output by 'location_zip_code', 'yr'. You can override
using the `.groups` argument.
avg_sales_by_zip
# A tibble: 46 × 2
   location_zip_code avg_zip_sales
   <chr>                     <dbl>
 1 78701                 25942124.
 2 78704                  9214430.
 3 78758                  6329404.
 4 78702                  5514537.
 5 78703                  2344716.
 6 78759                  1899343.
 7 78748                  1712802.
 8 78752                  1674980.
 9 78757                  1480878.
10 78735                  1390114.
# ℹ 36 more rows

Data Takeaway: On average, the ZIP codes 78701, 78704 and 78758 sell the most alcohol, respectively.

Which neighborhoods have the lowest average sales?

Now I will rearrange the data to look at the ZIP codes with lowest average sales. To do this I am grouping the data by location_zip_code, then using summarize() to calculate the averages of the total_receipts. Then I am arranging the data by location_zip_code in ascending order so that the data is showing the ZIP codes with least average sales from top to bottom.

avg_sales_by_zip |>
  arrange(avg_zip_sales)
# A tibble: 46 × 2
   location_zip_code avg_zip_sales
   <chr>                     <dbl>
 1 78774                     1369.
 2 78713                     8593.
 3 78742                    13890.
 4 78739                    35148.
 5 78733                    36377.
 6 78724                    44431.
 7 78721                    50716.
 8 78754                    50795.
 9 78747                    59197.
10 78736                    71135.
# ℹ 36 more rows

Data Takeaway: On average, the ZIP codes 78774, 78713 and 78742 sell the least amount of alcohol, respectively.

Visualization: Sales by ZIP code

I will create a map that displays Austin alcohol sales by ZIP code in Datawrapper. I will be using this chart for my summary.

First, I am taking the avg_sales_by_zip I created in the last section and exporting the data for Datawrapper.

# Exporting for Datawrapper
avg_sales_by_zip |> write_csv("data-processed/avg_sales_by_zip.csv")

The avg_sales_by_zip graphic:

This visualization can also be found here: https://www.datawrapper.de/_/Md5BY/

Average October sales (ACL)

Which neighborhoods see the largest spikes in sales during ACL in October?

First, I am grouping the data by location_zip_code, yr and mo_label, then using summarise() to calculate the sums of the total_receipts.

# Calculate total sales per ZIP, year and month
monthly_sales_zip <- mixedbev |> 
  group_by(location_zip_code, yr, mo_label) |> 
  summarize(monthly_sales_totals = sum(total_receipts), .groups = "drop")

monthly_sales_zip
# A tibble: 2,670 × 4
   location_zip_code    yr mo_label monthly_sales_totals
   <chr>             <dbl> <ord>                   <dbl>
 1 78660              2019 Jan                    107431
 2 78660              2019 Feb                     99171
 3 78660              2019 Mar                    129945
 4 78660              2019 Apr                    122340
 5 78660              2019 May                    128043
 6 78660              2019 Jun                    138109
 7 78660              2019 Jul                    129294
 8 78660              2019 Aug                    145547
 9 78660              2019 Sep                    159989
10 78660              2019 Oct                    152105
# ℹ 2,660 more rows

Then, I am calculating the the average monthly totals for October. To do this I filter for mo_label == “Oct”, group the data by the data by location_zip_code, and use summarise to get the mean of the monthly_sales_totals . Then I arrange the data by the averages (avg_october_sales_zip).

# Calculate average monthly totals for October
average_october_sales <- monthly_sales_zip |> 
  filter(mo_label == "Oct") |> 
  group_by(location_zip_code) |> 
  summarise(avg_october_sales_zip = mean(monthly_sales_totals), .groups = "drop") |>
  arrange(desc(avg_october_sales_zip))

average_october_sales
# A tibble: 46 × 2
   location_zip_code avg_october_sales_zip
   <chr>                             <dbl>
 1 78701                         30604935 
 2 78704                         13702950.
 3 78758                          7098776.
 4 78702                          6236167.
 5 78703                          2593283.
 6 78759                          1920599.
 7 78748                          1863710 
 8 78752                          1845346 
 9 78712                          1762957.
10 78735                          1664269.
# ℹ 36 more rows

To analyze how October sales compared to yearly averages, I calculate the average yearly total alcohol sales for each ZIP code. First, I roup the data by location_zip_code and yr, and calculate the yearly total receipts for each ZIP code. Then, I group the data by location_zip_code again to calculate the average yearly sales across all years. Finally, I arrange the ZIP codes in descending order based on their average yearly sales.

# Calculate average yearly totals
average_yearly_sales <- monthly_sales_zip |> 
  group_by(location_zip_code, yr) |> 
  summarize(yearly_total = sum(monthly_sales_totals), .groups = "drop") |> 
  group_by(location_zip_code) |> 
  summarize(avg_yearly_sales = mean(yearly_total), .groups = "drop") |>
  arrange(desc(avg_yearly_sales))

average_yearly_sales
# A tibble: 46 × 2
   location_zip_code avg_yearly_sales
   <chr>                        <dbl>
 1 78701                   311305482 
 2 78704                   110573161.
 3 78758                    75952845.
 4 78702                    66174440.
 5 78703                    28136590.
 6 78759                    22792112.
 7 78748                    20553630.
 8 78752                    20099765 
 9 78757                    17770541.
10 78735                    16681370 
# ℹ 36 more rows

I join the average October sales data with the average yearly sales data to calculate the contribution of October sales to the yearly total for each ZIP code.

# Join averages
join_averages <- average_october_sales |> 
  left_join(average_yearly_sales, by = "location_zip_code")

join_averages
# A tibble: 46 × 3
   location_zip_code avg_october_sales_zip avg_yearly_sales
   <chr>                             <dbl>            <dbl>
 1 78701                         30604935        311305482 
 2 78704                         13702950.       110573161.
 3 78758                          7098776.        75952845.
 4 78702                          6236167.        66174440.
 5 78703                          2593283.        28136590.
 6 78759                          1920599.        22792112.
 7 78748                          1863710         20553630.
 8 78752                          1845346         20099765 
 9 78712                          1762957.        10917934.
10 78735                          1664269.        16681370 
# ℹ 36 more rows

Next, I need to calculate the percentage of average yearly sales that occurred in October. I first use mutate() to find the percentage for each ZIP code and round it to three decimal places. I then filter for ZIP codes where October sales contributed at least 10% of the yearly total and arrange in descending order.

# Calculate percentage
oct_sales_percentages <- join_averages |> 
  mutate(october_percentage = round((avg_october_sales_zip / avg_yearly_sales) * 100, 3)) |>
  filter(october_percentage >= 10) |>
  arrange(desc(october_percentage)) 

oct_sales_percentages
# A tibble: 8 × 4
  location_zip_code avg_october_sales_zip avg_yearly_sales october_percentage
  <chr>                             <dbl>            <dbl>              <dbl>
1 78712                          1762957.        10917934.               16.1
2 78736                           113541.          853618.               13.3
3 78713                            10493.           80202.               13.1
4 78704                         13702950.       110573161.               12.4
5 78733                            44872           385595                11.6
6 78722                           919702.         9089731.               10.1
7 78737                           383533.         3795001.               10.1
8 78719                          1567981.        15678001.               10.0

Data takeaway: The ZIP codes 78712, 78736 and 78713 make the highest average contributions to alcohol sales during October.

Visualization: October sales

I will use ggplot to create a bar chart from my data that shows the ZIP codes that make the highest average contribution to alcohol sales during October. I will be using this chart for my summary.

oct_sales_percentages |>
  ggplot(aes(
    x = reorder(location_zip_code, october_percentage),
    y = october_percentage,
    fill = factor(location_zip_code))) +
  geom_col(fill = "steelblue") +
  geom_text(aes(
    label = sprintf("%.2f", october_percentage)),
    vjust = 0.5,
    hjust = -0.2,
    color = "black") +
  coord_flip() + 
  labs(
    title = "Austin ZIP codes make higher contributions during ACL in October",
    subtitle = str_wrap("The ZIP codes 78712, 78736 and 78713 make the highest average contributions to alcohol sales during October."),
    caption = "By Gabriella Gonzales. Source: Texas Comptroller of Public Accounts",
    x = "ZIP Code",
    y = "October's average percentage of year sales (%)") +
  theme(
    plot.margin = margin(t = 10, r = 30, b = 10, l = 10)
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.1)))

ggsave("figures/oct_sales_percentages.png")
Saving 7 x 5 in image

October sales 2023

After looking at the average alcohol sales activity during October, I want to analyze on specific year. I will look at 2023 in this section.

The first step in analyzing October 2023 alcohol sales is to filter the monthly_sales_zip data for October (mo_label == “Oct”) and the year 2023 (yr == 2023). Then, I group the data by location_zip_code to calculate the total alcohol sales for October in each ZIP code. The summarize() function is used to sum up the sales, and the results are arranged in descending order.

# Filter October sales for 2023
october_2023_sales <- monthly_sales_zip |> 
  filter(mo_label == "Oct", yr == 2023) |> 
  group_by(location_zip_code) |> 
  summarize(october_2023_sales = sum(monthly_sales_totals), .groups = "drop") |> 
  arrange(desc(october_2023_sales))

october_2023_sales
# A tibble: 45 × 2
   location_zip_code october_2023_sales
   <chr>                          <dbl>
 1 78701                       35767283
 2 78704                       28137417
 3 78702                        8540954
 4 78758                        7239369
 5 78703                        3207811
 6 78712                        2426589
 7 78719                        2313270
 8 78748                        2269019
 9 78735                        2225663
10 78752                        2149455
# ℹ 35 more rows

Next, I calculate the total alcohol sales for the entire year of 2023 for each ZIP code. This step uses filter() to select data from 2023 (yr == 2023) and groups the data by location_zip_code. Then I use summarze() to get the totals.

# Total 2023 sales by ZIP code
yearly_2023_sales <- monthly_sales_zip |> 
  filter(yr == 2023) |> 
  group_by(location_zip_code) |> 
  summarize(total_sales_2023 = sum(monthly_sales_totals), .groups = "drop")

yearly_2023_sales
# A tibble: 46 × 2
   location_zip_code total_sales_2023
   <chr>                        <dbl>
 1 78660                      1642353
 2 78701                    399087970
 3 78702                    100750007
 4 78703                     37567394
 5 78704                    156173372
 6 78705                     17410334
 7 78712                     20451824
 8 78713                        95531
 9 78717                     11109755
10 78719                     24562943
# ℹ 36 more rows

This step combines the October sales (october_2023_sales) with the yearly totals (yearly_2023_sales) for 2023. I first use left_join() to join (yearly_2023_sales) (october_2023_sales) by location_zip_code. I created a new column, october_percentage_2023, to calculate October’s percentage of total yearly sales, rounded to three decimal places. The results are arranged in descending order of this percentage.

# Combine October and yearly sales data for 2023
sales_comparison_2023 <- october_2023_sales |> 
  left_join(yearly_2023_sales, by = "location_zip_code") |> 
  mutate(october_percentage_2023 = round((october_2023_sales / total_sales_2023) * 100, 3)) |> 
  arrange(desc(october_percentage_2023))

sales_comparison_2023
# A tibble: 45 × 4
   location_zip_code october_2023_sales total_sales_2023 october_percentage_2023
   <chr>                          <dbl>            <dbl>                   <dbl>
 1 78704                       28137417        156173372                   18.0 
 2 78736                         155056          1132850                   13.7 
 3 78712                        2426589         20451824                   11.9 
 4 78724                         181891          1604527                   11.3 
 5 78731                         663000          6666790                    9.94
 6 78735                        2225663         23114733                    9.63
 7 78719                        2313270         24562943                    9.42
 8 78754                         138443          1512445                    9.15
 9 78774                           1492            16433                    9.08
10 78738                         135207          1499453                    9.02
# ℹ 35 more rows

Next, I filter the data to show only those ZIP codes where October sales contributed more than 9.5% to the total yearly sales. This focuses the analysis on neighborhoods with significant sales spikes in October.

# Filter for significant October contributions
significant_october_sales <- sales_comparison_2023 |> 
  filter(october_percentage_2023 > 9.5)

significant_october_sales
# A tibble: 6 × 4
  location_zip_code october_2023_sales total_sales_2023 october_percentage_2023
  <chr>                          <dbl>            <dbl>                   <dbl>
1 78704                       28137417        156173372                   18.0 
2 78736                         155056          1132850                   13.7 
3 78712                        2426589         20451824                   11.9 
4 78724                         181891          1604527                   11.3 
5 78731                         663000          6666790                    9.94
6 78735                        2225663         23114733                    9.63

Data takeaway: The ZIP codes 78704, 78736 and 78712 made the highest contribution to alcohol sales during October 2023.

Visualization: October sales 2023

I will use ggplot to create a bar chart from my data that shows the ZIP codes that made the highest contribution to alcohol sales during October 2023. I will be using this chart for my summary.

# Bar chart for October percentage of total sales
significant_october_sales |>
  ggplot(aes(
    x = reorder(location_zip_code, october_percentage_2023),
    y = october_percentage_2023,
    fill = factor(location_zip_code))) +
  geom_col(fill = "steelblue") +
  geom_text(aes(
    label = sprintf("%.2f", october_percentage_2023)),
    vjust = 0.5,
    hjust = -0.2,
    color = "black") +
  coord_flip() + 
  labs(
    title = "Austin ZIP codes make higher contributions in October 2023",
    subtitle = str_wrap("The ZIP codes 78704, 78736 and 78712 made the highest contribution to alcohol sales during October 2023."),
    x = "ZIP Code",
    y = "October's percentage of 2023 sales (%)",
    caption = "By Gabriella Gonzales. Source: Texas Comptroller of Public Accounts"
  ) +
  theme(
    plot.margin = margin(t = 10, r = 30, b = 10, l = 10)
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.1)))

ggsave("figures/oct_2023_percentages.png")
Saving 7 x 5 in image

Average March sales (SXSW)

Which neighborhoods see the largest spikes in sales during SXSW in March?

I am taking monthly_sales_zip, filtering it for March, grouping by location_zip_code, then using summarize to get the average March sales for each ZIP code. Then I arrange in descending order of average sales.

# Calculate average monthly totals for October
average_march_sales <- monthly_sales_zip |> 
  filter(mo_label == "Mar") |> 
  group_by(location_zip_code) |> 
  summarize(avg_march_sales_zip = mean(monthly_sales_totals), .groups = "drop") |>
  arrange(desc(avg_march_sales_zip))

average_march_sales
# A tibble: 46 × 2
   location_zip_code avg_march_sales_zip
   <chr>                           <dbl>
 1 78701                       29983952.
 2 78704                        9725019 
 3 78758                        6521978.
 4 78702                        6398621.
 5 78703                        2405045.
 6 78759                        2050612 
 7 78748                        1899132.
 8 78728                        1868364.
 9 78752                        1731384.
10 78757                        1515592.
# ℹ 36 more rows

Similar to the October analysis, I join the March averages with yearly averages to evaluate the significance of March sales.

# Join averages
join_averages_mar <- average_march_sales |> 
  left_join(average_yearly_sales, by = "location_zip_code")

join_averages_mar
# A tibble: 46 × 3
   location_zip_code avg_march_sales_zip avg_yearly_sales
   <chr>                           <dbl>            <dbl>
 1 78701                       29983952.       311305482 
 2 78704                        9725019        110573161.
 3 78758                        6521978.        75952845.
 4 78702                        6398621.        66174440.
 5 78703                        2405045.        28136590.
 6 78759                        2050612         22792112.
 7 78748                        1899132.        20553630.
 8 78728                        1868364.        10821155.
 9 78752                        1731384.        20099765 
10 78757                        1515592.        17770541.
# ℹ 36 more rows

Next, I need to calculate the percentage of average yearly sales that occurred in March. I first use mutate() to find the percentage for each ZIP code and round it to three decimal places. I then filter for ZIP codes where March sales contributed at least 9.5% of the yearly total and arrange in descending order.

# Calculate percentage
mar_sales_percentages <- join_averages_mar |> 
  mutate(march_percentage = round((avg_march_sales_zip / avg_yearly_sales) * 100, 3)) |>
  filter(march_percentage >= 9.5) |>
  arrange(desc(march_percentage)) 

mar_sales_percentages
# A tibble: 9 × 4
  location_zip_code avg_march_sales_zip avg_yearly_sales march_percentage
  <chr>                           <dbl>            <dbl>            <dbl>
1 78742                          35233.          158348.            22.2 
2 78728                        1868364.        10821155.            17.3 
3 78713                          12766.           80202.            15.9 
4 78721                          62420.          608587.            10.3 
5 78727                         122440.         1218428.            10.0 
6 78736                          82899.          853618.             9.71
7 78702                        6398621.        66174440.             9.67
8 78701                       29983952.       311305482              9.63
9 78746                         847379.         8870022              9.55

Data takeaway: The ZIP codes 78742, 78728 and 78713 make the highest average contributions to alcohol sales during March.

Visualization: March sales

I will use ggplot to create a bar chart from my data that shows the ZIP codes that make the highest average contribution to alcohol sales during March. I will be using this chart for my summary.

mar_sales_percentages |>
  ggplot(aes(
    x = reorder(location_zip_code, march_percentage),
    y = march_percentage,
    fill = factor(location_zip_code))) +
  geom_col(fill = "steelblue") +
  geom_text(aes(
    label = sprintf("%.2f", march_percentage)),
    vjust = 0.5,
    hjust = -0.2,
    color = "black") +
  coord_flip() + 
  labs(
    title = "Austin ZIP codes make higher contributions during SXSW in March",
    subtitle = str_wrap("The ZIP codes 78742, 78728 and 78713 make the highest average contributions to alcohol sales during March."),
    caption = "By Gabriella Gonzales. Source: Texas Comptroller of Public Accounts",
    x = "ZIP Code",
    y = "March's average percentage of year sales (%)") +
  theme(
    plot.margin = margin(t = 10, r = 30, b = 10, l = 10)
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.1)))

ggsave("figures/mar_sales_percentages.png")
Saving 7 x 5 in image

March sales 2023

After looking at the average alcohol sales activity during March, I want to analyze on specific year. I will look at March 2023 in this section.

To analyze alcohol sales for March 2023, I started by filtering the monthly_sales_zip dataset for entries corresponding to March (mo_label == “Mar”) and the year 2023 (yr == 2023). After filtering, I grouped the data by location_zip_code and used the summarize() function to calculate the total sales for March in each ZIP code. Finally, I arranged the results in descending order to easily identify the areas with the highest sales.

# Filter March sales for 2023
march_2023_sales <- monthly_sales_zip |> 
  filter(mo_label == "Mar", yr == 2023) |> 
  group_by(location_zip_code) |> 
  summarize(march_2023_sales = sum(monthly_sales_totals), .groups = "drop") |> 
  arrange(desc(march_2023_sales))

march_2023_sales
# A tibble: 46 × 2
   location_zip_code march_2023_sales
   <chr>                        <dbl>
 1 78701                     41783582
 2 78704                     13908380
 3 78702                     10449360
 4 78758                      8199011
 5 78703                      3522316
 6 78728                      3001029
 7 78748                      2863574
 8 78759                      2353719
 9 78719                      2307194
10 78752                      2227954
# ℹ 36 more rows

Next, I combined the March sales data (march_2023_sales) with the yearly totals for 2023 (yearly_2023_sales). I used a left_join() on location_zip_code to merge the datasets and created a new column, march_percentage_2023, to calculate March’s percentage of the total annual sales for each ZIP code. I rounded these percentages to three decimal places and arranged the results in descending order to identify ZIP codes where March sales represented a significant portion of the yearly total.

# Combine March and yearly sales data for 2023
sales_comparison_march_2023 <- march_2023_sales |> 
  left_join(yearly_2023_sales, by = "location_zip_code") |> 
  mutate(march_percentage_2023 = round((march_2023_sales / total_sales_2023) * 100, 3)) |> 
  arrange(desc(march_percentage_2023))

sales_comparison_march_2023
# A tibble: 46 × 4
   location_zip_code march_2023_sales total_sales_2023 march_percentage_2023
   <chr>                        <dbl>            <dbl>                 <dbl>
 1 78728                      3001029         13050435                  23.0
 2 78742                        44774           223869                  20  
 3 78739                        57680           443668                  13.0
 4 78721                       111233           951971                  11.7
 5 78734                       229854          2164584                  10.6
 6 78733                        69554           658038                  10.6
 7 78701                     41783582        399087970                  10.5
 8 78702                     10449360        100750007                  10.4
 9 78748                      2863574         27871917                  10.3
10 78746                      1087265         10592070                  10.3
# ℹ 36 more rows

Next, I filter the data to show only those ZIP codes where March sales contributed more than 10% to the total yearly sales. This focuses the analysis on neighborhoods with significant sales contributions in March.

# Filter for significant March contributions
significant_march_sales <- sales_comparison_march_2023 |> 
  filter(march_percentage_2023 > 10)

significant_march_sales
# A tibble: 11 × 4
   location_zip_code march_2023_sales total_sales_2023 march_percentage_2023
   <chr>                        <dbl>            <dbl>                 <dbl>
 1 78728                      3001029         13050435                  23.0
 2 78742                        44774           223869                  20  
 3 78739                        57680           443668                  13.0
 4 78721                       111233           951971                  11.7
 5 78734                       229854          2164584                  10.6
 6 78733                        69554           658038                  10.6
 7 78701                     41783582        399087970                  10.5
 8 78702                     10449360        100750007                  10.4
 9 78748                      2863574         27871917                  10.3
10 78746                      1087265         10592070                  10.3
11 78713                         9556            95531                  10.0

Data takeaway: The ZIP codes 78728, 78742 and 78739 made the highest contribution to alcohol sales during October 2023.

Visualization: March sales 2023

# Bar chart for March percentage of total sales
significant_march_sales |>
  ggplot(aes(
    x = reorder(location_zip_code, march_percentage_2023),
    y = march_percentage_2023,
    fill = factor(location_zip_code))) +
  geom_col(fill = "steelblue") +
  geom_text(aes(
    label = sprintf("%.2f", march_percentage_2023)),
    vjust = 0.5,
    hjust = -0.2,
    color = "black") +
  coord_flip() + 
  labs(
    title = "Austin ZIP codes make higher contributions in March 2023",
    subtitle = str_wrap("The ZIP codes 78728, 78742 and 78739 made the highest contribution to alcohol sales during October 2023."),
    x = "ZIP Code",
    y = "March's percentage of 2023 sales (%)",
    caption = "By Gabriella Gonzales. Source: Texas Comptroller of Public Accounts"
  ) +
  theme(
    plot.margin = margin(t = 10, r = 30, b = 10, l = 10)
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.1)))

ggsave("figures/mar_2023_percentages.png")
Saving 7 x 5 in image