30 Day Chart Challenge 2025

The 30 Day Chart Challenge is a data visualisation challenge where participants create a chart for each daily prompt. In this blog post, I'll recap the charts I made during the 2025 challenge and discuss the data and tools I used, alongside what I learned during the process.

May 1, 2025

The 30 Day Chart Challenge is a data visualisation challenge organised by Cédric Scherer and Dominic Royé. Participants make one chart each day of the challenge, inspired by the daily prompt. The prompts are also split across 5 different categories, which for 2025 were comparisons, distributions, relationships, time series, and uncertainties.

30 day chart challenge prompts

I first participated in the 2022 edition of the challenge, and wrote a blog post about what I learned during the process. This year was the first time I managed to complete all 30 days since 2022, so I decided to write another blog post to do the same this year.

If you’re more into maps than charts, you might be interested in the 30 Day Map Challenge which takes place in November each year.

Before the challenge

Although I hadn’t fully committed myself to doing every day of the challenge at the start, I still thought it would be useful to think about what I wanted to get out of it. Having some aims for the month really helps when things get busy, and making more charts for fun doesn’t seem like much of a priority.

Aims

My main aims for the challenge were:

  • Spend time learning more Observable and D3: Until recently, I’ve primary used R (mainly {ggplot2}) to make charts. I’ve recently started learning more D3, and I wanted to use this as an opportunity to try different chart types in D3, and Observable.
  • Reuse datasets and visualise them different ways: In previous editions of the challenge, I often found myself spending a lot of time looking for the right dataset to make a particular chart type. This year, I wanted to save some time by re-using datasets for different prompts.
  • Use more text and annotations in charts: Adding annotations to charts can be really useful but, in comparison to point-and-click plotting tools, creating charts using code can sometimes make this more annoying to get right. So I wanted to spend a bit more time paying attention to text in chart.

As I worked through the prompts, I also decided I wanted to use it as a way to design more experimental charts - those that fall outside of the standard chart types, and may or may not be very effective.

During the challenge

I found some prompts much easier than others in terms of coming up with an idea for a chart. And so I ended up working on the prompts in a different order. For example, the day 29 chart was one of the first plots I created.

I also didn’t do one chart per day, I tended to batch them together. e.g. creating a trio of plots using the same software, and same chart styling for three different prompts.

What data did I visualise?

For day 1 of the challenge, I chose to use data from Our World in Data on income inequality represented by the share of income received by the richest 1% of the population. I chose this dataset because I thought it would work well for the Fractions prompt. After the first day, I decided to continue using this dataset for all of the prompts. Since one of my goals was to save time searching for data and re-use datasets, what better way to do that than force myself to create 30 charts for one dataset?

A couple of the prompts were Data prompts, so I did end up using another couple of datasets during the challenge. Although for those prompts, I visualised them alongside the income inequality data. On day 24, I used World Health Organization data on access to basic hand-washing facilities and again compared the trend of time with the trend in income inequality. I used data on the availability of dairy products in the USA, and compared the trend over time to the income inequality trend in the USA. I added a third dataset to this chart, via the presidential dataset in {ggplot2} in R, to add some additional context in the background of the time series data.

Chart showing (spurious) correlation between bird numbers and income inequality

Finally, for the Birds prompt, I was really struggling to figure out how income inequality data could fit that prompt, and eventually decided to use some data on bird populations to create a dual axis line chart, in the style of spurious correlations.

What tools did I use?

I used four different tools for building charts: R, Python, Observable, and D3.

Chart showing what tools were used to make charts, R highest, Python at the bottom

Although most were still made in R, in comparison to previous editions, this is my lowest percentage of R-created charts. That mainly reflects my goal of learning more Observable and D3. I probably use Observable as much as I’d planned, but that’s because something finally clicked in my head about how D3 works, and I was having more fun playing with it instead.

Most of my R charts were built with {ggplot2}, but I did also use this as an opportunity to try out the (reasonably new) {tidyplots} package. I really like how clean and tidy the default chart aesthetics are, and love how it still works so seamlessly with existing {ggplot2} functions and extension packages.

What charts did I make?

I won’t go into detail about all 30 of the charts I created, but I will highlight the one I like the most, and the one I’d like to remake.

ZgotmplZ

The one I like the most

Two waffle charts showing 1% and 21% represented people and money

This isn’t the most complex, or intricately designed chart but I really like it for two reasons:

  • It’s a minimalist design, but I think it’s still very effective.
  • It was built from scratch in D3, which is something I think would have found very difficult on Day 1 of the challenge, but by Day 28 I was able to just build it. This chart kind of marks a turning point in learning D3 for me.

The one I’d love to remake

A horribly bright, dual y-axis log scale chart

This (horrendous) chart was created for the Extraterrestrial prompt, which I interpreted as *a chart designed by an extraterrestrial who has never heard of good data visualisation principles". This one was designed deliberately badly, and I’d love to do a step-by-step walk through of how to make it better. Perhaps a future blog post will do just that.

You can browse all of the charts that I’ve made for this year and previous editions of the 30 Day Chart Challenge, using an interactive app built with Shinylive.

ZgotmplZ

You can also find the source code on GitHub.

After the challenge

What did I learn?

In terms of programming and technical learning, some of the highlights are:

  • Observable:

    • Editing imported chart
    • Formatting data formatting when passing between R and Observable
    • Creating custom tooltips

    Some of the things I’ve learned about Observable are written down in my Observable for R users blog post.

    Featured image for Observable for R users blog post

  • D3:

    • Working with D3 through Observable
    • Using D3 on its own
    • Using SVG icons and recolouring them
    • Fitting models and plotting fitted lines
    • Creating and loading custom colour palettes
  • Python:

    • Consistent label sizing in Plotnine
    • Data-driven art examples in Python
  • R:

    • Tried out the {tidyplots} package
    • Experimented with new charts types such as mirrored area charts, and star charts
    • Created dropdown menus with {ggiraph} and Javascript
    • Built a function to take a screenshot of charts built with Observable or D3 in an automated way, so that I could share them on social media more easily:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    save_js_png <- function(day, selector, ...) {
      httpuv::runStaticServer(
        dir = glue::glue("2025/scripts/day_{day}/"),
        port = 4000,
        background = TRUE,
        browse = FALSE
      )
      webshot2::webshot(
        url = "http://127.0.0.1:4000/",
        file = glue::glue("2025/viz/day_{day}.png"),
        selector = selector,
        ...
      )
      httpuv::stopAllServers()
    }
    

    The image is then saved in the right folder with a standardised name by simply calling:

    1
    
    save_js_png(day = 26, selector = "svg")
    

What would I still like to learn?

Some of the things I’d love to work on next:

  • Some examples of combining Python data processing and visualisation in Observable, via Quarto.
  • When creating visualisations in D3, I tended to process the data in R or Python first to get it into the right format and then save it as a CSV file. I’d like to see how much of that I could do directly in D3 alone.
  • Add some interaction into the charts I’ve created with D3, such as tooltips and dropdowns.

Advice for chart challenges

If you’re thinking about participating in a chart challenge (whether the 30 Day Chart Challenge or a different one), here are a couple of things I’d recommend:

  • Using the same data for multiple charts forces you to be creative when trying to work the prompts, but also saves you time finding data, processing data, and writing captions for source attribution.
  • Batch together several of the prompts, and creating multiple charts using the same tool and styling to save time.
  • Don’t feel like you have to stick to prompts too rigidly.
  • But mainly, use it as a learning opportunity rather than trying to make the perfect chart every day. It’s perfectly okay to share the less-than-perfect / work-in-progress / I wish I had more time versions of charts!

Favourite charts

I saw so many beautiful and interesting charts throughout the challenge, and it would be impossible to mention them all here, but these were a few of my particular favourites:

#30DayChartChallenge: Fractions 📊

I've tracked my daily mood and activities for more than 1,500 days. These are my moods visualized. An empty circle was a terrible day, while a full circle was a fantastic day.

[image or embed]

— Jacque Schrag (@jacqueschrag.com) 2 April 2025 at 02:39

#30DayChartChallenge Day 9. diverging #xfiles #dataviz

[image or embed]

— Ihar Yanouski (@iharyanouski.bsky.social) 10 April 2025 at 13:27

Well done to everyone who participated in this year’s challenge whether you made one or thirty charts!


For attribution, please cite this work as:

30 Day Chart Challenge 2025.
Nicola Rennie. May 1, 2025.
nrennie.rbind.io/blog/30-day-chart-challenge-2025
BibLaTeX Citation
@online{rennie2025,
  author = {Nicola Rennie},
  title = {30 Day Chart Challenge 2025},
  date = {2025-05-01},
  url = {https://nrennie.rbind.io/blog/30-day-chart-challenge-2025}
}

Licence: creativecommons.org/licenses/by/4.0