The James Beard Foundation Awards are annual honors recognizing excellence in the culinary, hospitality, and food media industries across the United States.
# Load the TidyTuesday datatuesdata<-tidytuesdayR::tt_load(2024, week =53)broadcast_media<-tuesdata$broadcast_mediatidytuesdayR::readme(tuesdata)# Remove the original list (tuesdata) from the environment to free up spacerm(tuesdata)
3. 🕵️ Examine the Data
Show code
# View data structureglimpse(broadcast_media)# Summary statisticsskim(broadcast_media)
4. 🤼 Wrangle Data
Show code
# Step 1: Get top 4 affiliations by frequencytop_affiliations<-broadcast_media%>%filter(year>=max(year)-5)%>%mutate(affiliation =str_split(affiliation, ","))%>%unnest(affiliation)%>%mutate(affiliation =str_trim(affiliation), affiliation =str_to_lower(affiliation))%>%group_by(affiliation)%>%count()%>%ungroup()%>%slice_max(order_by =n, n =4, with_ties =FALSE)%>%pull(affiliation)# Step 2: Filter rows with top affiliationsdf<-broadcast_media%>%filter(year>=max(year)-5)%>%mutate(affiliation =str_split(affiliation, ","))%>%unnest(affiliation)%>%mutate(affiliation =str_trim(affiliation), affiliation =str_to_lower(affiliation))%>%filter(str_detect(affiliation, paste(top_affiliations, collapse ="|")))%>%mutate(affiliation =str_extract(affiliation, paste(top_affiliations, collapse ="|")))# Step 3: Map logos to affiliationslogo_df<-tribble(~affiliation, ~logo,"youtube", "youtube_logo.png","netflix", "netflix_logo.png","itunes", "itunes_logo.png","instagram", "instagram_logo.png")|>mutate( logo =here::here("visualization", "TidyTuesday", "2024", "Week_53", "logo", logo))df<-df%>%left_join(logo_df, by ="affiliation")%>%mutate( logo_label =glue("<img src='{logo}' width='{ifelse(affiliation == 'itunes', 30, 50)}'/>"))# Step 5: Count rank occurrences per affiliationresults<-df%>%group_by(affiliation, rank)%>%count()%>%arrange(desc(n))# Step 6: Create summary text for plot facetsresults_text<-results%>%mutate(text =glue("{rank}: {n}"))%>%group_by(affiliation)%>%summarise(summary =paste(text, collapse ="\n"), .groups ="drop")# Step 7: Attach summary text to data for plottingdf<-df%>%left_join(results_text, by ="affiliation")# Step 8: Print dataframe for validationprint(df)
5. 🔤 Text
Show code
title<-"James Beard Awards Wins and Nominations Between 2019 to 2024"subtitle<-"Total Wins and Nominations for the Top Four Broadcast Media Across All Subcategories"# Create a social media caption with customized colors and font for consistency in visualizationsocial<-andresutils::social_caption(font_family ="Roboto Condensed", icon_color ="grey25")# Construct the final plot caption by combining TidyTuesday details, data source, and the social captioncap<-paste0("#TidyTuesday: Week 53, 2024 | **Source**: James Beard Foundation, Wikipedia, curated by Jon Harmon | **Graphic**: ", social)
6. 📊 Plot
Show code
# Step 1: Create base plot with dot plot, facet by logo, and summary textp<-df%>%ggplot(aes(x =factor(year), alpha =rank, fill =factor(year)))+geom_dotplot(method ="histodot", binwidth =1, stackdir ="up", stackgroups =TRUE, color="grey50", stackratio =0.75, dotsize =.8)+facet_wrap(vars(logo_label), nrow =1)+scale_alpha_manual(values =c(0.45, 1))+scale_fill_manual(values =c("#ef476f", "#ffd166", "#06d6a0", "#118ab2", "#073b4c"))+labs(title =title, subtitle =subtitle, caption =cap)+geom_text(data =df%>%distinct(affiliation, summary, .keep_all =TRUE),aes(x =-Inf, y =Inf, label =summary), hjust =0, vjust =1, inherit.aes =FALSE, family ="Roboto Condensed", size =2, color ="grey25")+theme_void()+theme( text =element_text(family ="Roboto Condensed"), plot.title =element_text(hjust =0.5, family ="Oswald", face ="bold", margin =margin(b =5, t =10)), plot.subtitle =element_text(hjust =0.5, margin =margin(b =10, t =0)), plot.margin =margin(5, 10, 5, 10), plot.background =element_rect(fill ="#ffffff", colour ="#ffffff"), panel.background =element_rect(fill ="#ffffff", colour ="#ffffff"), plot.caption =element_markdown(hjust =0.5, size =5, margin =margin(b =5, t =10)), axis.text.x =element_text(size =7), legend.position ="none", strip.text =element_markdown(hjust =0.5), panel.spacing =unit(1.5, "cm"))+coord_cartesian(clip ="off")# Step 2: Add curve annotations and text for the Instagram facetp2<-p+geom_curve(data =df%>%filter(affiliation=="instagram"),aes(x =2, y =0.4, xend =3, yend =0.3), arrow =arrow(length =unit(0.15, "cm"), type ="closed"), color ="grey25", linewidth =0.3, curvature =-0.3, inherit.aes =FALSE)+geom_text(data =df%>%filter(affiliation=="instagram"),aes(x =2, y =0.4, label ="Opaque dots\nshow wins"), color ="grey25", family ="Roboto Condensed", size =1.9, hjust =1)+geom_curve(data =df%>%filter(affiliation=="instagram"),aes(x =4.4, y =0.5, xend =4.4, yend =0.24), arrow =arrow(length =unit(0.15, "cm"), type ="closed"), color ="grey25", linewidth =0.3, curvature =0.8, inherit.aes =FALSE)+geom_text(data =df%>%filter(affiliation=="instagram"),aes(x =4.4, y =0.5, label ="Transparent dots\nshow nominations"), color ="grey25", family ="Roboto Condensed", size =1.9, hjust =0)
7. 💾 Save
Show code
# Save plot with dimensionsandresutils::save_plot(p2, type ="tidytuesday", year =2024, week =53, width =8, height =4.5)
8. 🚀 GitHub Repository
Expand for GitHub Repo
Explore the complete code for this visualization in the following Quarto file: tt_53_2024.qmd.
For additional visualizations and projects, click here.