In order to get a general idea how each sample looks, I chose to summarize them. To do so, I put each sample dataframe in a list, and used a for loop to summarize each one.
#defining sample size (about 500)
sample_size <- 500
#five new dataframes with randomly sampled data
df_1 <- book_sales[sample(nrow(book_sales), size = sample_size, replace = TRUE), , drop = FALSE]
df_2 <- book_sales[sample(nrow(book_sales), size = sample_size, replace = TRUE), , drop = FALSE]
df_3 <- book_sales[sample(nrow(book_sales), size = sample_size, replace = TRUE), , drop = FALSE]
df_4 <- book_sales[sample(nrow(book_sales), size = sample_size, replace = TRUE), , drop = FALSE]
df_5 <- book_sales[sample(nrow(book_sales), size = sample_size, replace = TRUE), , drop = FALSE]
#create a list of sample dataframes to loop through
df_list <- list(df_1, df_2, df_3, df_4, df_5)
#empty list to store results
publisher_sales_summary <- list()
#for each df in the df_list
for (i in seq_along(df_list)) {
current_df <- df_list[[i]]
summary_stats <- current_df |>
#group by publisher
group_by(Publisher) |>
#summarize columns
summarize(
total_units_sold = sum(`units sold`),
total_gross_sales = sum(`gross sales`),
total_publisher_revenue = sum(`publisher revenue`)
) |>
#arrange desc by total gross sales
arrange(desc(total_gross_sales))
publisher_sales_summary[[i]] <- summary_stats
}
print(publisher_sales_summary)
## [[1]]
## # A tibble: 7 × 4
## Publisher total_units_sold total_gross_sales total_publisher_reve…¹
## <chr> <dbl> <dbl> <dbl>
## 1 Amazon Digital Serv… 3242256 315321. 64772.
## 2 Penguin Group (USA)… 399595 155938. 93563.
## 3 Random House LLC 625767 119544. 71727.
## 4 HarperCollins Publi… 145269 51024. 30615.
## 5 Hachette Book Group 264371 28783. 17270.
## 6 Simon and Schuster … 183340 22055. 13233.
## 7 Macmillan 127017 13727. 8236.
## # ℹ abbreviated name: ¹​total_publisher_revenue
##
## [[2]]
## # A tibble: 7 × 4
## Publisher total_units_sold total_gross_sales total_publisher_reve…¹
## <chr> <dbl> <dbl> <dbl>
## 1 Amazon Digital Serv… 2419216 393557. 84785.
## 2 Penguin Group (USA)… 492521 145924. 87554.
## 3 Random House LLC 360961 139921. 83953.
## 4 Hachette Book Group 385083 101706. 61024.
## 5 HarperCollins Publi… 305084 62229. 37337.
## 6 Simon and Schuster … 244616 38723. 23234.
## 7 Macmillan 155305 32060. 19236.
## # ℹ abbreviated name: ¹​total_publisher_revenue
##
## [[3]]
## # A tibble: 7 × 4
## Publisher total_units_sold total_gross_sales total_publisher_reve…¹
## <chr> <dbl> <dbl> <dbl>
## 1 Amazon Digital Serv… 2529533 382027. 98357.
## 2 Penguin Group (USA)… 406776 145505. 87303.
## 3 Random House LLC 191713 138577. 83146.
## 4 Hachette Book Group 192933 94112. 56467.
## 5 HarperCollins Publi… 347010 90250. 54150.
## 6 Simon and Schuster … 140895 61723. 37034.
## 7 Macmillan 222154 28650. 17190.
## # ℹ abbreviated name: ¹​total_publisher_revenue
##
## [[4]]
## # A tibble: 7 × 4
## Publisher total_units_sold total_gross_sales total_publisher_reve…¹
## <chr> <dbl> <dbl> <dbl>
## 1 Amazon Digital Serv… 2644790 357531. 56497.
## 2 Penguin Group (USA)… 597968 182869. 109722.
## 3 Hachette Book Group 263536 148082. 88849.
## 4 Random House LLC 735772 128171. 76903.
## 5 HarperCollins Publi… 289785 91561. 54937.
## 6 Simon and Schuster … 320456 38679. 23207.
## 7 Macmillan 285105 20309. 12185.
## # ℹ abbreviated name: ¹​total_publisher_revenue
##
## [[5]]
## # A tibble: 7 × 4
## Publisher total_units_sold total_gross_sales total_publisher_reve…¹
## <chr> <dbl> <dbl> <dbl>
## 1 Amazon Digital Serv… 2875285 345715. 59287.
## 2 Hachette Book Group 224600 178674. 107205.
## 3 Penguin Group (USA)… 366816 167319. 100391.
## 4 Random House LLC 552013 144247. 86548.
## 5 HarperCollins Publi… 317670 73060. 43836.
## 6 Simon and Schuster … 208942 37384. 22430.
## 7 Macmillan 91935 20029. 12018.
## # ℹ abbreviated name: ¹​total_publisher_revenue
From this, we can see a few minor changes between each sampled dataframe. Amazon Digital Services, Inc. is consistently has the highest gross sales across all dataframes and Macmillan and Simon and Schuster Digital Sales Inc. consistently have the lowest gross sales, but spots two through four vary a bit.
I also wanted to get an idea on how book ratings vary between each dataframe.
author_sales_summary <- list()
#for each df in the df_list
for (i in seq_along(df_list)) {
current_df <- df_list[[i]]
summary_stats <- current_df |>
#group by author
group_by(Author) |>
summarize(
total_units_sold = sum(`units sold`),
total_gross_sales = sum(`gross sales`),
total_revenue = sum(`publisher revenue`),
total_ratings_count = sum(Book_ratings_count),
avg_book_rating = mean(Book_average_rating)
) |>
arrange(desc(total_gross_sales))
author_sales_summary[[i]] <- summary_stats
}
print(author_sales_summary)
## [[1]]
## # A tibble: 315 × 6
## Author total_units_sold total_gross_sales total_revenue total_ratings_count
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Laini T… 8990 38278. 22967. 284029
## 2 Frank M… 12500 24875 14925 290534
## 3 Stephen… 160955 24544. 3520. 1289729
## 4 Frances… 3666 23792. 14275. 199872
## 5 Nick Ho… 2268 21389. 12833. 236848
## 6 Sara Sh… 3200 15968 0 156328
## 7 Kate Mo… 12708 15388. 399. 594051
## 8 John Gr… 49506 14987. 1257. 647231
## 9 Michael… 33106 14862. 7744. 404541
## 10 Jodi Pi… 21585 13140. 6392. 677116
## # ℹ 305 more rows
## # ℹ 1 more variable: avg_book_rating <dbl>
##
## [[2]]
## # A tibble: 308 × 6
## Author total_units_sold total_gross_sales total_revenue total_ratings_count
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Harper … 5500 47795 28677 138669
## 2 Robert … 6532 32595. 0 278822
## 3 Sarah D… 4385 27376. 5647. 331136
## 4 Charlai… 6460 27148. 14863. 713509
## 5 John Be… 3800 26182 15709. 167997
## 6 Nick Ho… 2268 21389. 12833. 236848
## 7 Victori… 4000 19960 0 83354
## 8 J.R.R. … 3876 19341. 11605. 402318
## 9 James P… 10835 18250. 9780. 913644
## 10 Garth N… 882 17622. 10573. 274094
## # ℹ 298 more rows
## # ℹ 1 more variable: avg_book_rating <dbl>
##
## [[3]]
## # A tibble: 313 × 6
## Author total_units_sold total_gross_sales total_revenue total_ratings_count
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Harper … 11000 95590 57354 277338
## 2 Margery… 6666 43596. 26157. 346938
## 3 David S… 10873 41845. 24750 233489
## 4 Laini T… 13230 38604. 23163. 369775
## 5 Colleen… 9692 27180. 15656. 453164
## 6 Nichola… 13905 23065. 1207. 811775
## 7 Emily G… 2790 22832. 13699. 498807
## 8 Brandon… 7410 20706. 12424. 374141
## 9 Kenneth… 610 20655. 12393. 249224
## 10 Sarah D… 3600 17964 0 179415
## # ℹ 303 more rows
## # ℹ 1 more variable: avg_book_rating <dbl>
##
## [[4]]
## # A tibble: 329 × 6
## Author total_units_sold total_gross_sales total_revenue total_ratings_count
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Unknown… 7000 34160 20496 155903
## 2 John Gr… 52258 28158. 1823. 772544
## 3 Jeffrey… 8163 27984. 16791. 249800
## 4 Miguel … 2984 26826. 16096. 269862
## 5 John Be… 3800 26182 15709. 167997
## 6 Douglas… 3325 25701. 15420. 439238
## 7 Diana G… 8199 24515. 0 472185
## 8 Margery… 3333 21798. 13079. 173469
## 9 C.S. Le… 3600 21564 12938. 189671
## 10 Victori… 4000 19960 0 83354
## # ℹ 319 more rows
## # ℹ 1 more variable: avg_book_rating <dbl>
##
## [[5]]
## # A tibble: 316 × 6
## Author total_units_sold total_gross_sales total_revenue total_ratings_count
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 David S… 15320 82978. 49787. 383412
## 2 Laini T… 4750 37952. 22772. 198283
## 3 Unknown… 7000 34160 20496 155903
## 4 Robert … 6532 32595. 0 278822
## 5 Jeffrey… 2466 26904. 16142. 159249
## 6 John Be… 3800 26182 15709. 167997
## 7 John Gr… 7091 25479. 838. 379425
## 8 Stephen… 162309 22117. 6453. 1572567
## 9 Margery… 3333 21798. 13079. 173469
## 10 Brandon… 4696 21641. 11678. 442702
## # ℹ 306 more rows
## # ℹ 1 more variable: avg_book_rating <dbl>
There is a lot of variation in authors with the highest grossing sales between each dataframe, which I found to be very interesting and opens the door for more evaluation.
#combine the data for visualization
combined_data <- bind_rows(df_list, .id = "sample_number")
# Plot a boxplot
ggplot(combined_data, aes(x = factor(sample_number), y = `gross sales`)) +
geom_boxplot() +
labs(title = "Boxplot Comparison of Total Gross Sales for 5 Samples",
x = "Sample Number",
y = "Total Gross Sales")
I have previously had a lot of focus on gross sales, so in similar fashion I have decided to do a Monte Carlo simulation for the gross sales by author.
#simulation count
simulation_count <- 10
simulation_data <- book_sales
#empty list to store result
simulated_results <- list()
#begin monte carlo
for (i in 1:simulation_count) {
#duplicated data set with random variations
simulated_data <- mutate(simulation_data,
`gross sales` = rlnorm(n(), meanlog = log(mean(`gross sales`)), sdlog = sd(log(`gross sales`))) #log-normal distribution to prevent negative values because they do not make sense in this situation
)
#summary statistics
summary_stats <- simulated_data |>
group_by(Author) |>
summarize(
total_gross_sales = sum(`gross sales`)
) |>
arrange(desc(total_gross_sales))
simulated_results[[i]] <- summary_stats
}
#combine results into one dataframe to help with visualization
combined_results <- bind_rows(simulated_results)
# Plot distribution of total_gross_sales for one author
ggplot(combined_results, aes(x = total_gross_sales)) +
geom_histogram(bins = 30, fill = "aquamarine3", color = "black", alpha = 0.7) +
labs(title = "Distribution of Total Gross Sales (Monte Carlo Simulation)",
x = "Total Gross Sales",
y = "Frequency")
I have chosen to examine the book sales prices in each of my five samples to find instances where a price is an anomaly in one sample but not another. In order to do this, I started by creating a boxplot.
#combine the data for visualization
combined_data <- bind_rows(df_list, .id = "sample_number")
# Plot a boxplot
ggplot(combined_data, aes(x = factor(sample_number), y = `sale price`)) +
geom_boxplot() +
labs(title = "Boxplot Comparison of Book Sale Price",
x = "Sample Number",
y = "Sale Price")
Sample 5 looks like it contains a few outliers that are possibly not
outliers for sample 4. I decided to create an additonal box plot
highlighting this.
#combine only samples 4 and 5 for visualization
combined_data_4_5 <- bind_rows(df_list[c(4, 5)], .id = "sample_number")
#plot a boxplot
ggplot(combined_data_4_5, aes(x = factor(sample_number), y = `sale price`)) +
geom_boxplot() +
labs(title = "Boxplot Comparison of Book Sale Price",
x = "Sample Number",
y = "Sale Price")
Although the X labels say 1 and 2, the box plots show samples 4 and 5
respectively. Sample 5 (shown as 2 on the box plot) has a few anomalies
that appear as though they would fall between the upper quartile and
maximum for sample 4 (shown as 1 on the box plot). In order to pinpoint
more specific values, I proceeded to create a summaries for the samples
as seen below.
summary_4 <- summary(df_4$`sale price`)
print("Summary statistics for Sample 4:")
## [1] "Summary statistics for Sample 4:"
print(summary_4)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.990 1.990 3.990 4.956 7.190 33.860
summary_5 <- summary(df_5$`sale price`)
print("Summary statistics for Sample 5:")
## [1] "Summary statistics for Sample 5:"
print(summary_5)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.990 0.990 3.990 4.691 7.500 16.980
df_5_sorted <- df_5 |>
arrange(desc(`sale price`)) |>
head(5)
print("Sample 5 top 5 highest sales prices:")
## [1] "Sample 5 top 5 highest sales prices:"
print(df_5_sorted$`sale price`)
## [1] 16.98 15.37 14.99 14.99 14.99
df_4_sorted <- df_4 |>
arrange(desc(`sale price`)) |>
head(5)
print("Sample 4 top 5 highest sales prices:")
## [1] "Sample 4 top 5 highest sales prices:"
print(df_4_sorted$`sale price`)
## [1] 33.86 25.89 17.98 17.98 13.78