diff --git a/plots/bar-race-animated/implementations/r/ggplot2.R b/plots/bar-race-animated/implementations/r/ggplot2.R new file mode 100644 index 0000000000..81143ff2c6 --- /dev/null +++ b/plots/bar-race-animated/implementations/r/ggplot2.R @@ -0,0 +1,98 @@ +#' anyplot.ai +#' bar-race-animated: Animated Bar Chart Race +#' Library: ggplot2 3.5.1 | R 4.4.1 +#' Quality: 87/100 | Created: 2026-05-19 + +library(ggplot2) +library(dplyr) +library(scales) +library(ragg) +library(gapminder) + +set.seed(42) + +# Theme tokens +THEME <- Sys.getenv("ANYPLOT_THEME", "light") +PAGE_BG <- if (THEME == "light") "#FAF8F1" else "#1A1A17" +ELEVATED_BG <- if (THEME == "light") "#FFFDF6" else "#242420" +INK <- if (THEME == "light") "#1A1A17" else "#F0EFE8" +INK_SOFT <- if (THEME == "light") "#4A4A44" else "#B8B7B0" +OKABE_ITO <- c("#009E73", "#D55E00", "#0072B2", "#CC79A7", + "#E69F00", "#56B4E9", "#F0E442") + +# Data — top 10 countries by GDP per capita at 6 key snapshots +years_snap <- c(1952, 1967, 1977, 1987, 1997, 2007) + +df_snap <- gapminder::gapminder |> + filter(year %in% years_snap) |> + group_by(year) |> + slice_max(gdpPercap, n = 10, with_ties = FALSE) |> + ungroup() |> + mutate( + cntry_yr = paste0(country, "___", year), + cntry_yr = reorder(cntry_yr, gdpPercap) + ) + +continent_colors <- setNames( + OKABE_ITO[1:5], + c("Africa", "Americas", "Asia", "Europe", "Oceania") +) + +# Plot — small multiples replacing animation; each facet is one time snapshot +p <- ggplot(df_snap, aes(x = cntry_yr, y = gdpPercap, fill = continent)) + + geom_col(width = 0.8, alpha = 0.9) + + geom_text( + aes(label = label_dollar(scale = 1e-3, suffix = "K", accuracy = 1)(gdpPercap)), + hjust = -0.1, + color = INK_SOFT, + size = 4.5 + ) + + coord_flip() + + scale_x_discrete(labels = function(x) sub("___.*", "", x)) + + scale_y_continuous( + labels = label_dollar(scale = 1e-3, suffix = "K"), + expand = expansion(mult = c(0, 0.28)) + ) + + scale_fill_manual(values = continent_colors, name = "Continent") + + facet_wrap(~year, scales = "free", nrow = 2) + + labs( + title = "GDP per Capita Rankings · bar-race-animated · r · ggplot2 · anyplot.ai", + subtitle = "Kuwait leads in 1952 on oil wealth; European economies — especially Norway — rise to the top by 2007", + x = NULL, + y = "GDP per Capita (USD)" + ) + + theme_minimal(base_size = 14) + + theme( + plot.background = element_rect(fill = PAGE_BG, color = PAGE_BG), + panel.background = element_rect(fill = PAGE_BG, color = NA), + panel.grid.major.y = element_blank(), + panel.grid.major.x = element_line(color = INK_SOFT, linewidth = 0.25), + panel.grid.minor = element_blank(), + axis.title.x = element_text(color = INK, size = 20), + axis.title.y = element_blank(), + axis.text.x = element_text(color = INK_SOFT, size = 16), + axis.text.y = element_text(color = INK, size = 16), + plot.title = element_text(color = INK, size = 24, face = "bold", + margin = margin(b = 5)), + plot.subtitle = element_text(color = INK_SOFT, size = 18, + margin = margin(b = 15)), + legend.background = element_rect(fill = ELEVATED_BG, color = INK_SOFT, + linewidth = 0.3), + legend.text = element_text(color = INK_SOFT, size = 16), + legend.title = element_text(color = INK, size = 18), + legend.position = "bottom", + strip.text = element_text(color = INK, size = 18, face = "bold"), + strip.background = element_rect(fill = ELEVATED_BG, color = NA), + plot.margin = margin(15, 15, 10, 15) + ) + +# Save +ggsave( + filename = sprintf("plot-%s.png", THEME), + plot = p, + device = ragg::agg_png, + width = 16, + height = 9, + units = "in", + dpi = 300 +) diff --git a/plots/bar-race-animated/metadata/r/ggplot2.yaml b/plots/bar-race-animated/metadata/r/ggplot2.yaml new file mode 100644 index 0000000000..f08a8560f7 --- /dev/null +++ b/plots/bar-race-animated/metadata/r/ggplot2.yaml @@ -0,0 +1,264 @@ +library: ggplot2 +language: r +specification_id: bar-race-animated +created: '2026-05-19T02:10:39Z' +updated: '2026-05-19T02:29:50Z' +generated_by: claude-sonnet +workflow_run: 26071722470 +issue: 3653 +language_version: 4.4.1 +library_version: 3.5.1 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/r/ggplot2/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/r/ggplot2/plot-dark.png +preview_html_light: null +preview_html_dark: null +quality_score: 87 +review: + strengths: + - Correctly implements small multiples (facet_wrap) as the static alternative to + animation, per library spec and spec notes + - 'All font sizes properly set to recommended values: title 24pt, subtitle 18pt, + axis title 20pt, tick labels 16pt, legend 16pt, strip 18pt' + - Value labels on bars add meaningful data context without clutter + - Informative subtitle provides clear narrative insight about the GDP race + - Full theme-adaptive chrome (PAGE_BG, INK, INK_SOFT, ELEVATED_BG) correctly applied + to both themes + - 'Correct Okabe-Ito palette: Africa=#009E73 as first categorical series, full order + for 5 continents' + - The '___' separator trick for per-facet sorted bars is elegant and idiomatic ggplot2 + - set.seed(42) present; all imports used; clean linear script + weaknesses: + - geom_text value labels at size=4.5 are slightly small for a 4800x2700 canvas; + size 5.5-6.5 would be more legible at full resolution + - Design lacks a focal point — no highlighted country trajectory or callout annotation + to guide viewer attention across the chronological facets + - panel.border is not explicitly removed, leaving a box frame around each facet + panel; adding panel.border = element_blank() would add refinement + image_description: |- + Light render (plot-light.png): + Background: Warm off-white #FAF8F1 — correct, fills the full canvas including between facets + Chrome: Title "GDP per Capita Rankings · bar-race-animated · r · ggplot2 · anyplot.ai" in bold dark ink at 24pt — clearly readable. Subtitle at 18pt in secondary dark ink readable. Strip year labels (1952, 1967, 1977, 1987, 1997, 2007) in bold 18pt on elevated off-white backgrounds. X-axis label "GDP per Capita (USD)" at 20pt readable. Country names on y-axis at 16pt readable. Dollar tick labels on x-axis at 16pt readable. Legend at bottom shows continent colors with readable text. + Data: Horizontal bars colored by continent — Africa (#009E73 green), Americas (#D55E00 orange-red), Asia (#0072B2 blue), Europe (#CC79A7 reddish-purple), Oceania (#E69F00 orange-yellow). 6 facets in 2x3 grid show top-10 countries for years 1952, 1967, 1977, 1987, 1997, 2007. Value labels at bar ends (e.g. $108K for Kuwait in 1952). Bars sorted descending by value. Kuwait dominates 1952; Norway rises to top by 2007. + Legibility verdict: PASS — all text is readable against the light background, no light-on-light failures. + + Dark render (plot-dark.png): + Background: Warm near-black #1A1A17 — correct, fills canvas completely + Chrome: Title in primary light ink (#F0EFE8) — fully readable. Subtitle in secondary light ink — readable. Strip year labels in bright light text on dark elevated (#242420) backgrounds. Country names on y-axis in primary light ink — readable. X-axis tick labels in secondary ink token (#B8B7B0) — readable. Legend shows identical continent colors with light text against elevated dark background. No dark-on-dark failures detected; chrome adapts correctly. + Data: Bar colors are identical to the light render — Africa green, Americas orange, Asia blue, Europe purple, Oceania yellow-orange. Consistency is correct. Value labels at bar ends visible in INK_SOFT (#B8B7B0). Subtle x-axis vertical grid lines visible against dark background. + Legibility verdict: PASS — all text is readable against the dark background, chrome adapts correctly. + criteria_checklist: + visual_quality: + score: 27 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: Title 24pt, subtitle 18pt, axis title 20pt, tick labels 16pt, legend + 16pt, strip 18pt all correctly sized; geom_text value labels at size=4.5 + slightly below optimal for 4800x2700 canvas but readable + - id: VQ-02 + name: No Overlap + score: 5 + max: 6 + passed: true + comment: No collisions; slight crowding in facets with many short bars but + expand=c(0,0.28) gives adequate space for value labels + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: All bars clearly visible at alpha=0.9; five continents well-differentiated; + value labels at bar ends add clarity + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Okabe-Ito is CVD-safe; five continents well-differentiated; no red-green + as sole signal + - id: VQ-05 + name: Layout & Canvas + score: 3 + max: 4 + passed: true + comment: 2x3 facet grid works well for 6 time snapshots on landscape canvas; + slight internal crowding with 10 bars per panel + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: GDP per Capita (USD) with units on x-axis; no y-axis label needed + since country names are self-explanatory + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'Africa=#009E73 as first categorical series; full Okabe-Ito order + for 5 continents; background #FAF8F1 light / #1A1A17 dark; both renders + theme-correct' + design_excellence: + score: 14 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 6 + max: 8 + passed: true + comment: 'Above default (4): intentional continent-based color hierarchy, + bold title with narrative subtitle, strip backgrounds using elevated colors, + consistent typographic hierarchy; limited by no highlighted trajectory or + focal annotations' + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: 'Above default (2): y-axis grid removed, x-axis grid very subtle + at 0.25 linewidth, no minor grid, strip backgrounds use ELEVATED_BG; panel.border + not explicitly removed' + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: 'Above default (2): narrative subtitle gives clear insight; chronological + facet progression tells the arc; continent colors reveal geographic patterns; + no highlighted trajectory or callout annotations' + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Small multiples via facet_wrap is the correct and specified static + alternative for ggplot2; correctly renders each time snapshot as a sorted + bar chart + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Bars sorted by value per time point via slice_max+reorder; entity + labels on y-axis; time indicator via facet strip labels; consistent entity + colors across all frames + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: X=GDP per capita value, Y=ranked countries, fill=continent, facets=year; + all data correctly mapped + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title 'GDP per Capita Rankings · bar-race-animated · r · ggplot2 + · anyplot.ai' matches required format; legend labels are continent names + with correct colors + data_quality: + score: 14 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 5 + max: 6 + passed: true + comment: Shows ranked bars, time evolution, entity tracking, category coloring, + and value annotations; individual country trajectory hard to follow across + facets by nature of format + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Uses real gapminder historical data; GDP per capita values are authentic + and politically neutral + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: $0K-$108K range is realistic; dollar formatting with K suffix is + appropriate for the domain + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: Linear script with no functions or classes + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: set.seed(42) present; gapminder is a fixed deterministic dataset + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: All 5 imports (ggplot2, dplyr, scales, ragg, gapminder) are actually + used + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: The '___' separator trick for per-facet sorted bars is a genuine + idiomatic ggplot2 pattern; clean dplyr piping; no fake UI elements + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves as plot-{THEME}.png via sprintf; uses ragg::agg_png device + correctly + library_mastery: + score: 7 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: 'Excellent grammar-of-graphics: aes mapping, facet_wrap with free + scales, coord_flip, scale_fill_manual, scale_x_discrete with label function, + expansion(), proper theme layering; not full 5 due to no panel.border removal' + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: reorder(cntry_yr, gdpPercap) with '___' separator is a genuine ggplot2-specific + pattern for sorted faceted bars; scales::label_dollar with suffix; expansion(mult) + for label room; above default (1) but not maximally distinctive + verdict: APPROVED +impl_tags: + dependencies: + - gapminder + techniques: + - faceting + - annotations + patterns: + - dataset-loading + - groupby-aggregation + dataprep: [] + styling: + - alpha-blending