From ec7caab590ca43c6a763f48e38ccb156f954a83b Mon Sep 17 00:00:00 2001
From: palewire
Date: Wed, 29 Oct 2025 16:25:34 -0400
Subject: [PATCH 1/5] docs: add missing annotation class references to
multiple-column-charts
Add documentation references for MultipleColumnXRangeAnnotation,
MultipleColumnYRangeAnnotation, MultipleColumnXLineAnnotation, and
MultipleColumnYLineAnnotation classes. Also adds section headers for
existing MultipleColumnChart, MultipleColumnTextAnnotation, and
MultipleColumnRangeAnnotation references to improve documentation
structure and discoverability.
---
.../charts/multiple-column-charts.md | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/docs/user-guide/charts/multiple-column-charts.md b/docs/user-guide/charts/multiple-column-charts.md
index 94fa3bd..2989c44 100644
--- a/docs/user-guide/charts/multiple-column-charts.md
+++ b/docs/user-guide/charts/multiple-column-charts.md
@@ -174,14 +174,44 @@ chart.create()
## Reference
+### MultipleColumnChart
+
```{eval-rst}
.. parameter-table:: datawrapper.charts.MultipleColumnChart
```
+### MultipleColumnTextAnnotation
+
```{eval-rst}
.. parameter-table:: datawrapper.charts.MultipleColumnTextAnnotation
```
+### MultipleColumnRangeAnnotation
+
```{eval-rst}
.. parameter-table:: datawrapper.charts.MultipleColumnRangeAnnotation
```
+
+### MultipleColumnXRangeAnnotation
+
+```{eval-rst}
+.. parameter-table:: datawrapper.charts.MultipleColumnXRangeAnnotation
+```
+
+### MultipleColumnYRangeAnnotation
+
+```{eval-rst}
+.. parameter-table:: datawrapper.charts.MultipleColumnYRangeAnnotation
+```
+
+### MultipleColumnXLineAnnotation
+
+```{eval-rst}
+.. parameter-table:: datawrapper.charts.MultipleColumnXLineAnnotation
+```
+
+### MultipleColumnYLineAnnotation
+
+```{eval-rst}
+.. parameter-table:: datawrapper.charts.MultipleColumnYLineAnnotation
+```
From 7307152116b384b239e7f69bbfc1ecd6b7b6a3ff Mon Sep 17 00:00:00 2001
From: palewire
Date: Thu, 30 Oct 2025 10:16:06 -0400
Subject: [PATCH 2/5] docs: update Datawrapper chart embed ID in stacked bar
example
Updated the embedded Datawrapper chart ID from j4JDS to VVR4V in the stacked bar chart documentation example. Also clarified the stack_percentages parameter comment to better describe its purpose as "Enable percentage stacking" rather than "Display values as percentages" to avoid confusion with the separate value_label_format parameter.
---
docs/user-guide/charts/stacked-bar-charts.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/user-guide/charts/stacked-bar-charts.md b/docs/user-guide/charts/stacked-bar-charts.md
index 023e012..22657d5 100644
--- a/docs/user-guide/charts/stacked-bar-charts.md
+++ b/docs/user-guide/charts/stacked-bar-charts.md
@@ -2,7 +2,7 @@
This example, drawn from [Datawrapper's official documentation](https://www.datawrapper.de/charts/stacked-bars), demonstrates how to create a diverging stacked bar chart showing trust levels in media reporting across different topics. The chart displays percentages with a [custom color scheme](https://colorbrewer2.org/#type=diverging&scheme=PRGn&n=5) to differentiate between trust levels, sorted by low trust values. It also includes value formatting.
-
+
```python
import pandas as pd
@@ -24,7 +24,7 @@ chart = dw.StackedBarChart(
source_url="http://www.infratest-dimap.de/umfragen-analysen/bundesweit/umfragen/aktuell/wenig-vertrauen-in-medienberichterstattung/",
# Data from pandas DataFrame
data=df,
- # Display values as percentages
+ # Enable percentage stacking
stack_percentages=True,
# Format value labels as percentages
value_label_format="0%",
From fdb18893f1bc5887719331c52005ff8bc6ba53ca Mon Sep 17 00:00:00 2001
From: palewire
Date: Thu, 30 Oct 2025 13:00:03 -0400
Subject: [PATCH 3/5] feat(scatter): add color column and category
customization support
Add support for coloring scatter plot points by column values with customizable category colors, labels, and ordering. This includes:
- New `color_column` field to specify which column determines point colors
- `color_category` mapping for custom category colors
- `category_labels` for custom legend display names
- `category_order` to control category appearance order
- `exclude_from_color_key` to hide specific categories from legend
- Serialization/deserialization logic using ColorCategory utility
- Updated documentation with new color customization examples
This enhancement allows users to create more informative scatter plots by encoding an additional dimension through color while maintaining full control over the visual presentation.
---
datawrapper/charts/scatter.py | 50 +++-
docs/user-guide/charts/scatter-plots.md | 336 +++++++++++++++++++-----
2 files changed, 322 insertions(+), 64 deletions(-)
diff --git a/datawrapper/charts/scatter.py b/datawrapper/charts/scatter.py
index 8650804..97d8daa 100644
--- a/datawrapper/charts/scatter.py
+++ b/datawrapper/charts/scatter.py
@@ -15,7 +15,7 @@
ScatterSize,
)
from .models import AnnotationsMixin
-from .serializers import PlotHeight
+from .serializers import ColorCategory, PlotHeight
class ScatterPlot(AnnotationsMixin, BaseChart):
@@ -198,6 +198,41 @@ class ScatterPlot(AnnotationsMixin, BaseChart):
description="Whether to show the color key",
)
+ #: The column with the color for the points
+ color_column: str = Field(
+ default="",
+ alias="color-column",
+ description="The column with the color for the points",
+ )
+
+ #: A mapping of layer names to colors
+ color_category: dict[str, str] = Field(
+ default_factory=dict,
+ alias="color-category",
+ description="A mapping of layer names to colors",
+ )
+
+ #: Dictionary mapping category names to their display labels in the color legend
+ category_labels: dict[str, str] = Field(
+ default_factory=dict,
+ alias="category-labels",
+ description="Dictionary mapping category names to their display labels in the color legend",
+ )
+
+ #: List defining the order in which categories appear in the chart and legend
+ category_order: list[str] = Field(
+ default_factory=list,
+ alias="category-order",
+ description="List defining the order in which categories appear in the chart and legend",
+ )
+
+ #: A list of column to exclude from the color key
+ exclude_from_color_key: list[str] = Field(
+ default_factory=list,
+ alias="exclude-from-color-key",
+ description="A list of column to exclude from the color key",
+ )
+
#
# Size
#
@@ -498,6 +533,8 @@ def serialize_model(self) -> dict:
axes["shape"] = self.shape_column
if self.label_column:
axes["labels"] = self.label_column
+ if self.color_column:
+ axes["color"] = self.color_column
# Add axes to metadata
model["metadata"]["axes"] = axes
@@ -529,6 +566,13 @@ def serialize_model(self) -> dict:
"outlines": self.outlines,
"color-outline": self.color_outline,
"show-color-key": self.show_color_key,
+ "color-category": ColorCategory.serialize(
+ self.color_category,
+ self.category_labels,
+ self.category_order,
+ self.exclude_from_color_key,
+ ),
+ "color-by-column": bool(self.color_category),
# Size
"size": self.size,
"fixed-size": self.fixed_size,
@@ -604,6 +648,7 @@ def deserialize_model(cls, api_response: dict[str, Any]) -> dict[str, Any]:
init_data["size_column"] = axes.get("size")
init_data["shape_column"] = axes.get("shape")
init_data["label_column"] = axes.get("labels")
+ init_data["color_column"] = axes.get("color")
# Parse x-axis
x_axis = visualize.get("x-axis", {})
@@ -653,6 +698,9 @@ def deserialize_model(cls, api_response: dict[str, Any]) -> dict[str, Any]:
if "show-color-key" in visualize:
init_data["show_color_key"] = visualize["show-color-key"]
+ # Parse color-category using utility
+ init_data.update(ColorCategory.deserialize(visualize.get("color-category")))
+
# Size
if "size" in visualize:
init_data["size"] = visualize["size"]
diff --git a/docs/user-guide/charts/scatter-plots.md b/docs/user-guide/charts/scatter-plots.md
index dc19258..bf9b121 100644
--- a/docs/user-guide/charts/scatter-plots.md
+++ b/docs/user-guide/charts/scatter-plots.md
@@ -1,8 +1,8 @@
# ScatterPlot
-This example, drawn from [Datawrapper's official documentation](https://www.datawrapper.de/charts/scatter-plot), demonstrates how to create a scatter plot showing the relationship between GDP per capita and life expectancy over time. The chart uses bubble size to represent population and features text annotations to label specific countries and years.
+This example, drawn from [Datawrapper's official documentation](https://www.datawrapper.de/charts/scatter-plot), demonstrates how to create a scatter plot.
-
+
```python
import pandas as pd
@@ -27,9 +27,10 @@ chart = dw.ScatterPlot(
# Data from pandas DataFrame
data=df,
# Define which columns to use for each dimension
- x_column="GPD",
- y_column="Health",
+ x_column="gdp",
+ y_column="health",
size_column="population",
+ color_column="countries",
label_column="country",
# Use logarithmic scale for x-axis (GDP)
x_log=True,
@@ -41,11 +42,18 @@ chart = dw.ScatterPlot(
y_format="0a",
# Configure bubble size
size="dynamic",
- max_size=60,
+ max_size=71.09,
# Set opacity for better visibility of overlapping bubbles
- opacity=0.6,
+ opacity=0.97,
# Set base color for all points
- base_color="#15607a",
+ base_color="#afafaf",
+ # Configure color categories for specific countries
+ color_category={
+ "China": "#ae000b",
+ "India": "#15607a",
+ "Somalia": "#c86300",
+ "United States": "#976f3a",
+ },
# Set fixed plot height
plot_height_fixed=581,
# Disable automatic labeling (we'll add custom text annotations)
@@ -59,65 +67,266 @@ chart = dw.ScatterPlot(
| {{ health }} years |
- {{ FORMAT(gdp, "0,0") }} Int'l$ |
-
+
{{ gdp }} Dollar |
+
+
""",
+ # Add custom lines connecting 1800 and 2015 data points for each country
+ custom_lines="""220,1.5,220,45,1000000,45,1000000,1.5 @color:grey @opacity:0.1
+220,46,220,92,1000000,92,1000000,46 @color:grey @opacity:0.1
+1925,53.8,603,28.21@color:grey @opacity:0.1
+10620,78,667,35.4@color:grey @opacity:0.1
+13434,76.4,716,28.82@color:grey @opacity:0.1
+7615,59.6,618,26.98@color:grey @opacity:0.1
+21049,76.4,757,33.54@color:grey @opacity:0.1
+17344,76.5,1507,33.2@color:grey @opacity:0.1
+7763,74.7,514,34@color:grey @opacity:0.1
+37138,75.72,833,34.42@color:grey @opacity:0.1
+44056,82.3,815,34.05@color:grey @opacity:0.1
+44401,81.3,1848,34.4@color:grey @opacity:0.1
+16986,72.9,775,29.17@color:grey @opacity:0.1
+22818,73.7,1445,35.18@color:grey @opacity:0.1
+44138,79.1,1235,30.3@color:grey @opacity:0.1
+3161,70.4,876,25.5@color:grey @opacity:0.1
+12984,75.7,913,32.12@color:grey @opacity:0.1
+17415,71,608,36.2@color:grey @opacity:0.1
+41240,80.5,2412,40@color:grey @opacity:0.1
+8501,71.7,579,26.5@color:grey @opacity:0.1
+1830,62.3,597,31@color:grey @opacity:0.1
+7983,72.7,629,28.8@color:grey @opacity:0.1
+6295,73.2,854,33@color:grey @opacity:0.1
+9833,78.9,669,35.1@color:grey @opacity:0.1
+17196,58.7,397,33.6@color:grey @opacity:0.1
+15441,74.4,1109,32@color:grey @opacity:0.1
+73003,77.1,1512,29.2@color:grey @opacity:0.1
+16371,74.8,1089,35.8@color:grey @opacity:0.1
+1654,60.9,480,29.2@color:grey @opacity:0.1
+777,61.4,418,31.5@color:grey @opacity:0.1
+3267,69.4,903,35@color:grey @opacity:0.1
+2897,59.4,626,28.75@color:grey @opacity:0.1
+43294,81.7,1314,39@color:grey @opacity:0.1
+6514,72.9,529,33.8@color:grey @opacity:0.1
+599,49.6,424,30@color:grey @opacity:0.1
+2191,57.4,418,30.9@color:grey @opacity:0.1
+22465,79.4,1026,32@color:grey @opacity:0.1
+13334,76.2,985,32@color:#B10615 @width:2
+12761,78,963,32@color:grey @opacity:0.1
+1472,68.1,696,32.1@color:grey @opacity:0.1
+809,60.8,485,31.6@color:grey @opacity:0.1
+6220,61.5,575,32.7@color:grey @opacity:0.1
+14132,80.3,775,30.21@color:grey @opacity:0.1
+3491,59.1,812,31.16@color:grey @opacity:0.1
+21291,78.2,864,32.2@color:grey @opacity:0.1
+29797,81.8,853,38.5@color:grey @opacity:0.1
+29437,78.8,1915,34.95@color:grey @opacity:0.1
+43495,80.4,2013,37.41@color:grey @opacity:0.1
+3139,63.8,752,29.9@color:grey @opacity:0.1
+12837,75.3,667,29.9@color:grey @opacity:0.1
+10996,75.9,529,32.9@color:grey @opacity:0.1
+11031,71.5,791,33@color:grey @opacity:0.1
+7776,74.9,974,28.7@color:grey @opacity:0.1
+31087,61,356,29.8@color:grey @opacity:0.1
+1129,60.7,532,30.2@color:grey @opacity:0.1
+26812,77.8,938,36.14@color:grey @opacity:0.1
+1520,65.2,523,29.7@color:grey @opacity:0.1
+7925,65.8,785,26.1@color:grey @opacity:0.1
+38923,80.9,1244,36.57@color:grey @opacity:0.1
+37599,81.8,1803,33.97@color:grey @opacity:0.1
+18627,65.9,390,30.6@color:grey @opacity:0.1
+1644,68.1,813,28.8@color:grey @opacity:0.1
+7474,72.9,543,31.87@color:grey @opacity:0.1
+44053,80.8,1639,38.37@color:grey @opacity:0.1
+4099,65.3,696,28@color:grey @opacity:0.1
+25430,81,1371,36.6@color:grey @opacity:0.1
+27763,72.1,393,33.87@color:grey @opacity:0.1
+11593,71.5,959,31.4@color:grey @opacity:0.1
+7279,72.6,857,25.8@color:grey @opacity:0.1
+1225,59.1,450,29.5@color:grey @opacity:0.1
+1386,55.6,777,32@color:grey @opacity:0.1
+6816,66.8,1214,31.12@color:grey @opacity:0.1
+1710,64.3,633,29@color:grey @opacity:0.1
+4270,73,675,33.9@color:grey @opacity:0.1
+53874,83.73,1007,34.9@color:grey @opacity:0.1
+24200,76.7,1249,36@color:grey @opacity:0.1
+42182,83.3,926,42.85@color:grey @opacity:0.1
+5903,67.2,1052,25.44@color:#1A637B @width:2
+10504,71.1,994,30@color:grey @opacity:0.1
+15573,74.6,977,25.6@color:grey @opacity:0.1
+14646,67.4,970,31.2@color:grey @opacity:0.1
+47758,81.7,1447,38.3@color:grey @opacity:0.1
+31590,82.1,879,32@color:grey @opacity:0.1
+33297,82.2,2225,29.69@color:grey @opacity:0.1
+8606,75,1170,34.2@color:grey @opacity:0.1
+36162,83.2,1050,36.4@color:grey @opacity:0.1
+11752,78.5,976,31.7@color:grey @opacity:0.1
+23468,70.2,1140,26.2@color:grey @opacity:0.1
+2898,65.1,854,25.5@color:grey @opacity:0.1
+1824,63,551,24.9@color:grey @opacity:0.1
+82633,80.3,1097,26@color:grey @opacity:0.1
+3245,69.8,508,23.94@color:grey @opacity:0.1
+5212,67.1,864,31.9@color:grey @opacity:0.1
+23282,75.4,751,33@color:grey @opacity:0.1
+17050,78.9,1081,29.7@color:grey @opacity:0.1
+2598,47.1,393,32.8@color:grey @opacity:0.1
+958,63.2,797,31.1@color:grey @opacity:0.1
+17261,74.1,1050,33.1@color:grey @opacity:0.1
+26665,75.2,1270,28.9@color:grey @opacity:0.1
+88314,82.2,1453,36.9@color:grey @opacity:0.1
+148374,80.82,992,34.7@color:grey @opacity:0.1
+12547,76.5,690,36.1@color:grey @opacity:0.1
+1400,63.5,573,30.5@color:grey @opacity:0.1
+799,60.5,350,30.3@color:grey @opacity:0.1
+24320,75.3,997,30.6@color:grey @opacity:0.1
+14408,80,842,32.65@color:grey @opacity:0.1
+1684,60.2,603,26.41@color:grey @opacity:0.1
+30265,82.1,781,28.7@color:grey @opacity:0.1
+3877,69.7,527,32@color:grey @opacity:0.1
+18350,74.5,940,28.7@color:grey @opacity:0.1
+16850,75.9,1379,26.9@color:grey @opacity:0.1
+3510,68.9,518,26.7@color:grey @opacity:0.1
+4896,73.9,621,33.15@color:grey @opacity:0.1
+11819,67.1,592,31.8@color:grey @opacity:0.1
+14833,77.2,1057,35.4@color:grey @opacity:0.1
+7319,74.6,715,33.1@color:grey @opacity:0.1
+1176,57.1,390,30.28@color:grey @opacity:0.1
+4012,68,840,30.8@color:grey @opacity:0.1
+10040,64.2,540,32.4@color:grey @opacity:0.1
+2352,69.7,654,32.8@color:grey @opacity:0.1
+45784,81.3,4235,39.86@color:grey @opacity:0.1
+34186,81.4,658,34.05@color:grey @opacity:0.1
+4712,78,973,25.4@color:grey @opacity:0.1
+943,61,446,30.8@color:grey @opacity:0.1
+5727,64.6,851,30.4@color:grey @opacity:0.1
+1390,72.1,579,26@color:grey @opacity:0.1
+64304,82,1278,37.92@color:grey @opacity:0.1
+48226,77.2,915,32.3@color:grey @opacity:0.1
+4743,65.9,1021,25.8@color:grey @opacity:0.1
+20485,78.2,847,32.9@color:grey @opacity:0.1
+2529,60.9,546,31.5@color:grey @opacity:0.1
+8219,74.4,835,35.5@color:grey @opacity:0.1
+11903,79.5,1204,35.7@color:grey @opacity:0.1
+6876,71,962,30.9@color:grey @opacity:0.1
+24787,77.6,1213,35.9@color:grey @opacity:0.1
+26437,80.8,1685,35.6@color:grey @opacity:0.1
+33604,78.5,1375,30.43@color:grey @opacity:0.1
+132877,79.7,1097,30.8@color:grey @opacity:0.1
+19203,75.2,815,35.7@color:grey @opacity:0.1
+23038,71,1430,29.57@color:grey @opacity:0.1
+1549,65.9,431,31.8@color:grey @opacity:0.1
+5558,73.2,1400,25.4@color:grey @opacity:0.1
+3003,68,850,31@color:grey @opacity:0.1
+52469,79.5,846,32.1@color:grey @opacity:0.1
+2251,65.3,497,25.2@color:grey @opacity:0.1
+12908,76.2,1358,35.5@color:grey @opacity:0.1
+25684,74.1,792,37@color:grey @opacity:0.1
+2085,57.1,734,25.1@color:grey @opacity:0.1
+80794,82,1021,29.1@color:grey @opacity:0.1
+27204,77.6,1427,36.4@color:grey @opacity:0.1
+28550,80.9,1409,36.6@color:grey @opacity:0.1
+2047,64,363,25.1@color:grey @opacity:0.1
+624,54.2,694,29.4@color:#CA670D @width:2
+12509,61.3,1480,33.5@color:grey @opacity:0.1
+34644,81,576,25.8@color:grey @opacity:0.1
+3047,56.1,507,26.67@color:grey @opacity:0.1
+32979,82.6,1518,29.5@color:grey @opacity:0.1
+10624,77.6,898,32.6@color:grey @opacity:0.1
+9997,74.8,874,28.01@color:grey @opacity:0.1
+10435,71.2,838,25.99@color:grey @opacity:0.1
+3975,67.5,518,31.4@color:grey @opacity:0.1
+17125,72,1636,32.9@color:grey @opacity:0.1
+6095,51.8,490,32.3@color:grey @opacity:0.1
+44892,82.1,1414,32.16@color:grey @opacity:0.1
+56118,83,2701,38@color:grey @opacity:0.1
+4637,68.2,1081,31.1@color:grey @opacity:0.1
+42948,79.5,996,28.3@color:grey @opacity:0.1
+2582,72.4,556,24.24@color:grey @opacity:0.1
+2571,64.1,562,32.2@color:grey @opacity:0.1
+14512,74.7,931,30.4@color:grey @opacity:0.1
+2086,72.4,521,28.95@color:grey @opacity:0.1
+1433,61.5,682,31.3@color:grey @opacity:0.1
+5069,71.5,663,28.2@color:grey @opacity:0.1
+30113,72.4,1230,32.9@color:grey @opacity:0.1
+11126,77.6,716,28.8@color:grey @opacity:0.1
+19360,79.2,1221,35@color:grey @opacity:0.1
+15865,70,943,24@color:grey @opacity:0.1
+1680,61.3,464,25.3@color:grey @opacity:0.1
+8449,71.5,763,36.6@color:grey @opacity:0.1
+60749,75.4,998,30.7@color:grey @opacity:0.1
+38225,81,3431,38.65@color:grey @opacity:0.1
+53354,79.1,2128,39.41@color:#9A7340 @width:2
+20438,76.8,1758,32.9@color:grey @opacity:0.1
+5598,71.8,502,26.93@color:grey @opacity:0.1
+2912,64.9,585,24.3@color:grey @opacity:0.1
+15753,74.8,682,32.2@color:grey @opacity:0.1
+5623,75.4,861,32@color:grey @opacity:0.1
+4319,74.6,1220,32.1@color:grey @opacity:0.1
+3887,66,877,23.39@color:grey @opacity:0.1
+4034,56.7,663,32.6@color:grey @opacity:0.1
+1801,59.3,869,33.7@color:grey @opacity:0.1""",
# Add text annotations to label years and key countries
text_annotations=[
- {
- "text": "1800",
- "x": 156700,
- "y": 45,
- "align": "tr",
- "dx": -14,
- "dy": 13,
- "bold": True,
- "size": 18,
- },
- {
- "text": "2015",
- "x": 156700,
- "y": 92,
- "align": "tr",
- "dx": -14,
- "dy": 13,
- "bold": True,
- "size": 18,
- },
- {
- "text": "China",
- "x": "13398.7010",
- "y": "76.1317",
- "align": "mc",
- "color": "#000000",
- "size": 13,
- },
- {
- "text": "India",
- "x": "5997.2352",
- "y": "67.2308",
- "align": "mc",
- "color": "#000000",
- "size": 13,
- },
- {
- "text": "Somalia",
- "x": 620,
- "y": 55.5,
- "align": "tl",
- "dx": 10,
- "dy": -1,
- "color": "#000000",
- "size": 13,
- },
- {
- "text": "US",
- "x": "53787.2503",
- "y": "79.0931",
- "align": "mc",
- "color": "#000000",
- "size": 13,
- },
+ dw.TextAnnotation(
+ text="1800",
+ x=156700,
+ y=45,
+ align="tr",
+ dx=-14,
+ dy=13,
+ bold=True,
+ size=22,
+ color="#000000",
+ outline=False,
+ ),
+ dw.TextAnnotation(
+ text="2015",
+ x=156700,
+ y=92,
+ align="tr",
+ dx=-14,
+ dy=13,
+ bold=True,
+ size=22,
+ color="#000000",
+ outline=False,
+ ),
+ dw.TextAnnotation(
+ text="China",
+ x="13398.7010",
+ y="76.1317",
+ align="mc",
+ color="#efefef",
+ size=13,
+ outline=False,
+ ),
+ dw.TextAnnotation(
+ text="India",
+ x="5997.2352",
+ y="67.2308",
+ align="mc",
+ color="#efefef",
+ size=13,
+ outline=False,
+ ),
+ dw.TextAnnotation(
+ text="Somalia",
+ x=620,
+ y=55.5,
+ align="tl",
+ dx=10,
+ dy=-1,
+ color="#983c00",
+ size=13,
+ outline=False,
+ ),
+ dw.TextAnnotation(
+ text="US",
+ x="53787.2503",
+ y="79.0931",
+ align="mc",
+ color="#efefef",
+ size=13,
+ outline=False,
+ ),
],
)
@@ -129,3 +338,4 @@ chart.create()
```{eval-rst}
.. parameter-table:: datawrapper.charts.ScatterPlot
+```
From 634dbe2c3a56b79d11a8b8a63018f7a6bc744ffe Mon Sep 17 00:00:00 2001
From: palewire
Date: Thu, 30 Oct 2025 13:04:19 -0400
Subject: [PATCH 4/5] feat(scatter): conditionally set color_column only when
color axis exists
Previously, color_column was always set using axes.get("color"), which would
assign None when the color key didn't exist. This change only sets color_column
in init_data when a color axis is explicitly defined, preventing unnecessary
None assignments and improving data structure clarity.
---
datawrapper/charts/scatter.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/datawrapper/charts/scatter.py b/datawrapper/charts/scatter.py
index 97d8daa..be4e13e 100644
--- a/datawrapper/charts/scatter.py
+++ b/datawrapper/charts/scatter.py
@@ -648,7 +648,8 @@ def deserialize_model(cls, api_response: dict[str, Any]) -> dict[str, Any]:
init_data["size_column"] = axes.get("size")
init_data["shape_column"] = axes.get("shape")
init_data["label_column"] = axes.get("labels")
- init_data["color_column"] = axes.get("color")
+ if "color" in axes:
+ init_data["color_column"] = axes["color"]
# Parse x-axis
x_axis = visualize.get("x-axis", {})
From a8293314bb7680e1b2e63ea508c8dffc6cf3d342 Mon Sep 17 00:00:00 2001
From: Ben Welsh
Date: Thu, 30 Oct 2025 13:05:19 -0400
Subject: [PATCH 5/5] Update datawrapper/charts/scatter.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
datawrapper/charts/scatter.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/datawrapper/charts/scatter.py b/datawrapper/charts/scatter.py
index be4e13e..d8f0402 100644
--- a/datawrapper/charts/scatter.py
+++ b/datawrapper/charts/scatter.py
@@ -226,11 +226,11 @@ class ScatterPlot(AnnotationsMixin, BaseChart):
description="List defining the order in which categories appear in the chart and legend",
)
- #: A list of column to exclude from the color key
+ #: A list of columns to exclude from the color key
exclude_from_color_key: list[str] = Field(
default_factory=list,
alias="exclude-from-color-key",
- description="A list of column to exclude from the color key",
+ description="A list of columns to exclude from the color key",
)
#