Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create publication-quality scientific figures with ggplot2 including scatter plots, boxplots, heatmaps, and multi-panel layouts. Use when creating static figures for papers, presentations, or reports in R.
.claude/skills/bio-data-visualization-ggplot2-fundamentals/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 71% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 169% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 50% | 0% |
| case-21 | ✓→✗ | ▼ Worse | 80% | 0% |
| case-07 | ✓→✗ | ▼ Worse | 61% | 0% |
<!--
#
#
-->
rlibrary(ggplot2) # Grammar of graphics: data + aesthetics + geometry ggplot(data, aes(x = var1, y = var2)) + geom_point()
r# Scatter plot ggplot(df, aes(x, y)) + geom_point() # Line plot ggplot(df, aes(x, y)) + geom_line() # Bar plot ggplot(df, aes(x, y)) + geom_col() # y values ggplot(df, aes(x)) + geom_bar() # counts # Boxplot ggplot(df, aes(group, value)) + geom_boxplot() # Violin plot ggplot(df, aes(group, value)) + geom_violin() # Histogram ggplot(df, aes(x)) + geom_histogram(bins = 30) # Density ggplot(df, aes(x, fill = group)) + geom_density(alpha = 0.5) # Heatmap ggplot(df, aes(x, y, fill = value)) + geom_tile()
r# Color by group ggplot(df, aes(x, y, color = group)) + geom_point() # Size by value ggplot(df, aes(x, y, size = value)) + geom_point() # Shape by category ggplot(df, aes(x, y, shape = category)) + geom_point() # Fill for bars/boxes ggplot(df, aes(x, y, fill = group)) + geom_boxplot() # Alpha for transparency ggplot(df, aes(x, y, alpha = value)) + geom_point()
rtheme_publication <- function(base_size = 12) { theme_bw(base_size = base_size) + theme( panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_rect(color = 'black', linewidth = 0.5), axis.text = element_text(color = 'black'), axis.ticks = element_line(color = 'black'), legend.key = element_blank(), strip.background = element_blank(), strip.text = element_text(face = 'bold') ) } # Usage ggplot(df, aes(x, y)) + geom_point() + theme_publication()
rlibrary(RColorBrewer) library(viridis) # Qualitative (categorical) scale_color_brewer(palette = 'Set1') scale_fill_brewer(palette = 'Set2') # Sequential (continuous) scale_fill_viridis_c() scale_color_gradient(low = 'white', high = 'red') # Diverging scale_fill_gradient2(low = 'blue', mid = 'white', high = 'red', midpoint = 0) scale_fill_distiller(palette = 'RdBu') # Manual colors scale_color_manual(values = c('Control' = '#1f77b4', 'Treatment' = '#d62728'))
rvolcano_plot <- function(res, fdr = 0.05, lfc = 1) { res <- res %>% mutate( significance = case_when( padj < fdr & log2FoldChange > lfc ~ 'Up', padj < fdr & log2FoldChange < -lfc ~ 'Down', TRUE ~ 'NS' ) ) ggplot(res, aes(log2FoldChange, -log10(pvalue), color = significance)) + geom_point(alpha = 0.6, size = 1) + scale_color_manual(values = c('Up' = '#d62728', 'Down' = '#1f77b4', 'NS' = 'grey60')) + geom_vline(xintercept = c(-lfc, lfc), linetype = 'dashed', color = 'grey40') + geom_hline(yintercept = -log10(fdr), linetype = 'dashed', color = 'grey40') + labs(x = 'Log2 Fold Change', y = '-Log10 P-value') + theme_publication() }
rma_plot <- function(res, fdr = 0.05) { res <- res %>% mutate(significant = padj < fdr) ggplot(res, aes(log10(baseMean), log2FoldChange, color = significant)) + geom_point(alpha = 0.5, size = 1) + scale_color_manual(values = c('TRUE' = 'red', 'FALSE' = 'grey60')) + geom_hline(yintercept = 0, color = 'black') + labs(x = 'Log10 Mean Expression', y = 'Log2 Fold Change') + theme_publication() }
rggplot(df, aes(group, value, fill = group)) + geom_boxplot(outlier.shape = NA, alpha = 0.7) + geom_jitter(width = 0.2, alpha = 0.5, size = 1) + scale_fill_brewer(palette = 'Set2') + labs(x = NULL, y = 'Expression') + theme_publication() + theme(legend.position = 'none')
r# Wrap by one variable ggplot(df, aes(x, y)) + geom_point() + facet_wrap(~ group, scales = 'free') # Grid by two variables ggplot(df, aes(x, y)) + geom_point() + facet_grid(rows = vars(condition), cols = vars(timepoint))
rlibrary(ggrepel) ggplot(res, aes(log2FoldChange, -log10(pvalue))) + geom_point() + geom_text_repel( data = subset(res, padj < 0.01), aes(label = gene), max.overlaps = 20, size = 3 )
rlibrary(patchwork) p1 <- ggplot(df, aes(x, y)) + geom_point() p2 <- ggplot(df, aes(group, value)) + geom_boxplot() p3 <- ggplot(df, aes(x)) + geom_histogram() # Combine horizontally p1 + p2 + p3 # Combine with layout (p1 | p2) / p3 # Add labels (p1 + p2 + p3) + plot_annotation(tag_levels = 'A') # Shared legend (p1 + p2) + plot_layout(guides = 'collect')
r# For publication (300 DPI) ggsave('figure.pdf', p, width = 7, height = 5, units = 'in') ggsave('figure.png', p, width = 7, height = 5, units = 'in', dpi = 300) ggsave('figure.tiff', p, width = 7, height = 5, units = 'in', dpi = 300, compression = 'lzw') # For presentations ggsave('figure.png', p, width = 10, height = 6, dpi = 150)
rlibrary(scales) # Scientific notation scale_y_continuous(labels = scientific) # Comma separators scale_x_continuous(labels = comma) # Log scale scale_y_log10(labels = trans_format('log10', math_format(10^.x))) # Percent scale_y_continuous(labels = percent) # Limits coord_cartesian(xlim = c(0, 10), ylim = c(0, 100)) # Breaks scale_x_continuous(breaks = seq(0, 10, 2))
r# Position theme(legend.position = 'bottom') theme(legend.position = 'none') theme(legend.position = c(0.8, 0.2)) # Title labs(color = 'Condition', fill = 'Group') guides(color = guide_legend(title = 'Condition')) # Order scale_color_discrete(limits = c('Control', 'Treatment'))
rlibrary(pheatmap) library(RColorBrewer) pheatmap( mat, scale = 'row', color = colorRampPalette(rev(brewer.pal(9, 'RdBu')))(100), cluster_rows = TRUE, cluster_cols = TRUE, show_rownames = TRUE, show_colnames = TRUE, annotation_col = annotation_df, fontsize = 8, filename = 'heatmap.pdf', width = 8, height = 10 )
<!-- AUTHOR_SIGNATURE: 9a7f3c2e-MD-BABU-MIA-2026-MSSM-SECURE -->
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 17,689 | 13,457 | -24% | 1 | 1 | 0% | 4,060 | 5,357 | +32% | 0 | 0 | — |
case-02 | fail→pass | 10,712 | 7,229 | -33% | 1 | 1 | 0% | 2,332 | 3,977 | +71% | 0 | 0 | — |
case-03 | pass→pass | 14,171 | 9,333 | -34% | 1 | 1 | 0% | 2,795 | 4,308 | +54% | 0 | 0 | — |
case-04 | pass→pass | 16,771 | 16,225 | -3% | 1 | 1 | 0% | 3,575 | 5,793 | +62% | 0 | 0 | — |
case-05 | pass→pass | 5,608 | 5,396 | -4% | 1 | 1 | 0% | 1,146 | 3,383 | +195% | 0 | 0 | — |
case-15 | fail→fail | 11,746 | 8,496 | -28% | 1 | 1 | 0% | 2,300 | 4,123 | +79% | 0 | 0 | — |
case-11 | pass→pass | 10,428 | 3,597 | -66% | 1 | 1 | 0% | 1,904 | 3,047 | +60% | 0 | 0 | — |
case-12 | pass→pass | 11,933 | 6,576 | -45% | 1 | 1 | 0% | 2,393 | 3,709 | +55% | 0 | 0 | — |
case-13 | fail→fail | 10,452 | 10,130 | -3% | 1 | 1 | 0% | 2,058 | 4,402 | +114% | 0 | 0 | — |
case-16 | fail→pass | 5,280 | 2,564 | -51% | 1 | 1 | 0% | 1,038 | 2,789 | +169% | 0 | 0 | — |
case-21 | pass→fail | 11,435 | 8,676 | -24% | 1 | 1 | 0% | 2,156 | 3,890 | +80% | 0 | 0 | — |
case-14 | pass→pass | 4,737 | 4,720 | -0% | 1 | 1 | 0% | 1,005 | 3,041 | +203% | 0 | 0 | — |
case-06 | fail→pass | 13,616 | 10,144 | -25% | 1 | 1 | 0% | 3,037 | 4,544 | +50% | 0 | 0 | — |
case-07 | pass→fail | 15,707 | 13,991 | -11% | 1 | 1 | 0% | 3,307 | 5,327 | +61% | 0 | 0 | — |
case-08 | pass→pass | 9,150 | 5,522 | -40% | 1 | 1 | 0% | 1,740 | 3,415 | +96% | 0 | 0 | — |
case-09 | pass→pass | 8,556 | 4,274 | -50% | 1 | 1 | 0% | 1,666 | 3,132 | +88% | 0 | 0 | — |
case-10 | fail→fail | 12,060 | 7,897 | -35% | 1 | 1 | 0% | 2,481 | 4,044 | +63% | 0 | 0 | — |
case-17 | pass→pass | 7,102 | 6,448 | -9% | 1 | 1 | 0% | 1,338 | 3,192 | +139% | 0 | 0 | — |
case-18 | pass→pass | 7,931 | 4,895 | -38% | 1 | 1 | 0% | 1,593 | 3,316 | +108% | 0 | 0 | — |
case-19 | fail→fail | 9,019 | 6,580 | -27% | 1 | 1 | 0% | 1,783 | 3,674 | +106% | 0 | 0 | — |
case-20 | pass→fail | 9,873 | 6,854 | -31% | 1 | 1 | 0% | 1,971 | 3,692 | +87% | 0 | 0 | — |
case-22 | pass→pass | 7,161 | 5,063 | -29% | 1 | 1 | 0% | 1,363 | 3,258 | +139% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of 0 percentage points is the difference between those two pass rates over the 22 comparable cases. 3 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 7/24/2026 | +5% |
Other measured skills in the registry, with their headline benchmark lift.