Less iteration, better charts
Rethinking how we create visualizations



Joseph Barbier - Rome R Users Group, 2026

We’re doing things all wrong…

  • Iteration has always been part of chart-making
  • AI has accelerated this loop dramatically
  • But faster iteration ≠ better outcomes


  • We should invert the process → design first, code last

The default workflow

Why this feels natural

  • Tools/AI encourage it: “I’ll just ask AI to do it to see how it looks”
  • Immediate feedback loop
  • Feels productive (but is it?)

Instead

Why does this chart need to exist?

  • Audience → who is this for?
  • Message → what should they understand?
  • Decision / action → what changes after seeing it?

Design before code

About


Consulting

Open source

Data(viz)

Example

df |> head() |> gt()
date price unit_sold sales
2023-04-07 99.44 323.4315 32162.03
2023-04-14 99.77 318.3910 31765.87
2023-04-21 101.56 323.1703 32821.17
2023-04-28 100.07 318.0495 31827.22
2023-05-05 100.13 325.1213 32554.40
2023-05-12 101.72 312.8675 31824.89

Context:

  • The company increased its price a few months ago from ~$100 to ~$115
  • Management wants to know the impact
  • What should we do?

Let’s check units sold

ggplot(df, aes(x = date, y = unit_sold)) + geom_line()

Far fewer units sold!

How about sales?

ggplot(df, aes(x = date, y = sales)) + geom_line()

But much higher sales!

Let’s compare them!

ggplot(df, aes(x = date)) +
    geom_line(aes(y = unit_sold)) +
    geom_line(aes(y = sales))

Wait, what?

Let’s put them next to each other

units_sold <- ggplot(df, aes(x = date, y = unit_sold)) + geom_line()
sales <- ggplot(df, aes(x = date, y = sales)) + geom_line()
units_sold + sales

What a diff! Oh wait, the scale is weird!

Adjust the scale

units_sold <- ggplot(df, aes(x = date, y = unit_sold)) +
    geom_line() +
    ylim(0, NA)
sales <- ggplot(df, aes(x = date, y = sales)) + geom_line() + ylim(0, NA)
units_sold + sales

Better, but most of the data is useless here

Reduce time period

df_filter <- df |> filter(date >= "2025-01-01")
units_sold <- ggplot(df_filter, aes(x = date, y = unit_sold)) +
    geom_line() +
    ylim(0, NA)
sales <- ggplot(df_filter, aes(x = date, y = sales)) + geom_line() + ylim(0, NA)
units_sold + sales

The trend isn’t really obvious now…

Let’s try to put them on the same chart

Sources:

But how do I compare them now?



“Your scientists were so preoccupied with whether or not they could, that they didn’t stop to think if they should.” Jurassic Park

Maybe we don’t need to?

p <- ggplot(df_filter, aes(x = date, y = sales)) +
    geom_line() +
    ylim(30000, 36500)
p

This chart should work with better styling and annotations

Change the theme

p <- p + theme_minimal()
p

Remove labels

p <- p + xlab("") + ylab("")
p

Update labels

p <- p +
    scale_y_continuous(labels = label_dollar(scale = 1e-3, suffix = "K")) +
    scale_x_date(labels = label_date("%b, %Y"), date_breaks = "3 months")
p

Increase their size

p <- p +
    theme(
        axis.text.x = element_text(size = 10),
        axis.text.y = element_text(size = 12, face = "bold")
    )
p

Highlight new price


Remove x grid


Move to the right

Getting better!

A colleague arrives…


“I think it’s important to also show units sold, and management wants a bar plot!”



  • Wait, so we need to start over?
  • OK, let’s do a bar plot then!
  • But what if management changes its mind?

Let’s do it differently

Define the goal

  • Goal: impact of the price change on:
    • units sold –> are we selling fewer units, and by how much?
    • sales –> are sales higher or lower, and by how much?

Create a design


Only rule: don’t rush it!

  • Figma
  • Canva
  • Excalidraw (personal preference)
  • Pen and paper
  • It doesn’t matter! Use whatever you prefer

Create a design

  • This takes much less time
  • Ask for feedback
  • And repeat!

Create a design



😱 Zero lines of code! Are we not productive???

  • We just did the hard part

Now we can code

  • With AI
    • Weak prompt: “Show sales evolution”
    • Strong prompt: “Create a bar plot for period X, highlight Y, remove Z, compare A and B, …”
  • Without AI
    • Much easier too!

Framework

  • Define intent
    • Who? What? Why?
  • Define the design
    • If you can’t visualize it, you’re not ready to code yet!
  • Feedback
    • Ask colleagues, managers, etc
  • Code

When is it okay to code first?

  • Get an overview of the data
    • AI can be very useful here
  • Design is already clear

Thanks for listening!


Did I say something wrong?

  • Come chat!

Did I say anything relevant?

  • Come chat!


Other?