newsworthycharts 1.60.1__py3-none-any.whl → 1.61.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- __version__ = "1.60.1"
1
+ __version__ = "1.61.1"
2
2
 
3
3
  from .chart import Chart
4
4
  from .choroplethmap import ChoroplethMap
newsworthycharts/chart.py CHANGED
@@ -667,7 +667,7 @@ class Chart(object):
667
667
  'Creator': f"NWCharts {__version__}",
668
668
  }
669
669
  """
670
- self._fig.savefig(buf, **args)
670
+ self._fig.savefig(buf, **args) # , bbox_inches="tight")
671
671
  buf.seek(0)
672
672
  self._storage.save(key, buf, img_format, storage_options)
673
673
 
@@ -716,7 +716,7 @@ class Chart(object):
716
716
  'Creator': f"NWCharts {__version__}",
717
717
  }
718
718
  """
719
- self._fig.savefig(buf, **args)
719
+ self._fig.savefig(buf, **args) #, bbox_inches="tight")
720
720
  buf.seek(0)
721
721
  self._storage.save(key, buf, file_format, storage_options)
722
722
 
@@ -6,6 +6,7 @@ import geopandas as gpd
6
6
  import numpy as np
7
7
  import pandas as pd
8
8
  import mapclassify
9
+ import matplotlib as mpl
9
10
  import matplotlib.patches as mpatches
10
11
 
11
12
 
@@ -50,11 +51,33 @@ class ChoroplethMap(Map):
50
51
  }
51
52
 
52
53
  patches = [] # for legend
53
- if not self.categorical:
54
+ if not self.categorical and self.use_bins is False:
55
+ # We can not provide vmin/vmax to geopandas, so we need to
56
+ # normalize the data ourselves, otherwise the inset maps will be off
57
+ norm = mpl.colors.Normalize(vmin=df["data"].min(), vmax=df["data"].max())
58
+ mapper = mpl.cm.ScalarMappable(norm=norm, cmap=self.color_ramp)
59
+ df["color"] = df["data"].apply(lambda x: mapper.to_rgba(x) if not np.isnan(x) else "gainsboro")
60
+ df["color"] = df["color"].fillna("gainsboro")
61
+ args["color"] = df["color"]
62
+
63
+ _min = df["data"].min()
64
+ _max = df["data"].max()
65
+ _median = df["data"].median()
66
+ fmt = self._get_value_axis_formatter()
67
+ patches.append(mpatches.Patch(color=mapper.to_rgba(_min), label=fmt(_min)))
68
+ if _median != _min and _median != _max:
69
+ patches.append(mpatches.Patch(color=mapper.to_rgba(_median), label=fmt(_median)))
70
+ if _max != _min:
71
+ patches.append(mpatches.Patch(color=mapper.to_rgba(_max), label=fmt(_max)))
72
+
73
+ elif not self.categorical:
54
74
  # mapclassify doesn't work well with nan values,
55
75
  # but we to keep them for plotting, hence
56
76
  # this hack with cutting out nan's and re-pasting them below
57
77
  _has_value = df[~df["data"].isna()].copy()
78
+ if not pd.to_numeric(_has_value['data'], errors='coerce').notnull().all():
79
+ # We can't bin non-numeric data
80
+ raise ValueError("Data must be numeric")
58
81
  binning = mapclassify.classify(
59
82
  np.asarray(_has_value["data"]), # .astype("category")
60
83
  self.binning_method,
@@ -75,10 +98,8 @@ class ChoroplethMap(Map):
75
98
  # args["cmap"] = self.color_ramp
76
99
  # We can not provide vmin/vmax to geopandas, so we need to
77
100
  # normalize the data ourselves, otherwise the inset maps will be off
78
- import matplotlib.cm as cm
79
- import matplotlib as mpl
80
101
  norm = mpl.colors.Normalize(vmin=df["data"].min(), vmax=df["data"].max())
81
- mapper = cm.ScalarMappable(norm=norm, cmap=self.color_ramp)
102
+ mapper = mpl.cm.ScalarMappable(norm=norm, cmap=self.color_ramp)
82
103
  df["color"] = df["data"].apply(lambda x: mapper.to_rgba(x) if not np.isnan(x) else "gainsboro")
83
104
  df["color"] = df["color"].fillna("gainsboro")
84
105
  args["color"] = df["color"]
@@ -130,6 +151,7 @@ class ChoroplethMap(Map):
130
151
  color = self._nwc_style[f"{color}_color"]
131
152
  patch = mpatches.Patch(color=color, label=label)
132
153
  patches.append(patch)
154
+ patches = list(reversed(patches))
133
155
  if self.missing_label:
134
156
  patches.append(mpatches.Patch(color="gainsboro", label=self.missing_label))
135
157
 
@@ -171,7 +193,8 @@ class ChoroplethMap(Map):
171
193
  for _line in [a, b, c, d]:
172
194
  _line.set_visible(False)
173
195
 
174
- self.ax.legend(
175
- handles=patches,
176
- **label_kwargs,
177
- )
196
+ if len(patches):
197
+ self.ax.legend(
198
+ handles=patches,
199
+ **label_kwargs,
200
+ )
newsworthycharts/map.py CHANGED
@@ -87,6 +87,7 @@ class Map(Chart):
87
87
  def __init__(self, *args, **kwargs):
88
88
  super(Map, self).__init__(*args, **kwargs)
89
89
  self.bins = kwargs.get("bins", 5)
90
+ self.use_bins = kwargs.get("use_bins", True)
90
91
  self.binning_method = kwargs.get("binning_method", "natural_breaks")
91
92
  self.colors = kwargs.get("colors", None)
92
93
  self.color_ramp = kwargs.get("color_ramp", "YlGn") # YlOrRd
@@ -46,7 +46,7 @@ class SerialChart(Chart):
46
46
  self.colors = None
47
47
 
48
48
  # Optional: where to place series label
49
- self.label_placement = "legend" # legend|inline|outside
49
+ self.label_placement = "legend" # legend|inline|outside|line
50
50
 
51
51
  # Optional: annotate each point with a value label
52
52
  self.value_labels = False
@@ -549,7 +549,12 @@ class SerialChart(Chart):
549
549
  _ = self.ax.legend(loc="best")
550
550
  _.set(zorder=20)
551
551
  elif self.label_placement == "outside":
552
- self.ax.legend(bbox_to_anchor=(0, 1, 1, 0), loc="lower right")
552
+ # mpl 3.7 has loc=outside, but it will lead to overlaps with titles
553
+ # also, has to be set on the figure, causing image size to change
554
+ _ = self.ax.legend(bbox_to_anchor=(1.04, 1), loc="upper left")
555
+ # self._fig.subplots_adjust(right=0.8)
556
+ # self._fig.tight_layout()
557
+ _.set(zorder=20)
553
558
  elif self.label_placement == "inline":
554
559
  labelLines(self.ax.get_lines(), align=False, zorder=13, outline_width=4, fontweight="bold")
555
560
 
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: newsworthycharts
3
- Version: 1.60.1
3
+ Version: 1.61.1
4
4
  Summary: Matplotlib wrapper to create charts and publish them on Amazon S3
5
5
  Home-page: https://github.com/jplusplus/newsworthycharts
6
- Download-URL: https://github.com/jplusplus/newsworthycharts/archive/1.60.1.tar.gz
6
+ Download-URL: https://github.com/jplusplus/newsworthycharts/archive/1.61.1.tar.gz
7
7
  Author: Jens Finnäs and Leo Wallentin, J++ Stockholm
8
8
  Author-email: stockholm@jplusplus.org
9
9
  License: MIT
@@ -21,9 +21,9 @@ Requires-Dist: python-dateutil <3,>=2
21
21
  Requires-Dist: Pillow ==10.4.0
22
22
  Requires-Dist: requests >=2.22
23
23
  Requires-Dist: matplotlib-label-lines ==0.5.1
24
- Requires-Dist: geopandas >1
24
+ Requires-Dist: geopandas >=1
25
25
  Requires-Dist: mapclassify ==2.6.1
26
- Requires-Dist: fiona >=1.10
26
+ Requires-Dist: puremagic >=1
27
27
 
28
28
  This module contains methods for producing graphs and publishing them on Amazon S3, or in the location of your choice.
29
29
 
@@ -167,7 +167,7 @@ These settings are available for all chart types:
167
167
  - value_labels = False # Print out values at points on line?
168
168
  - highlighted_x_ranges = [] # List of tuples with start and end of highlighted areas
169
169
  - x_range_labels = [] # List of labels for highlighted areas
170
- - label_placement = "legend" # legend|inline|outside
170
+ - label_placement = "legend" # legend|inline|outside|line
171
171
  - color_labels = None # A dictionary of label/color, to override style colors
172
172
 
173
173
  **SeasonalChart**
@@ -188,13 +188,14 @@ These settings are available for all chart types:
188
188
 
189
189
  **Map**
190
190
 
191
- - bins = 9 # Number of bins for continuous data
192
- - binning_method = "natural_breaks"
193
- - colors = None
194
- - color_ramp = "YlOrRd"
195
- - categorical = False # If True, the map will be colored by category. If False, it will be colored by a continuous value
196
- - base_map = None
197
- - missing_label = None # Add a label for no data
191
+ - `use_bins` = True # If False, the map will be colored by a continuous value
192
+ - `bins` = 5 # Number of bins for continuous data
193
+ - `binning_method` = "natural_breaks"
194
+ - `colors` = None
195
+ - `color_ramp` = "YlOrRd"
196
+ - `categorical` = False # If True, the map will be colored by category. If False, it will be colored by a continuous value
197
+ - `base_map` = None
198
+ - `missing_label` = None # Add a label for no data
198
199
 
199
200
  `basemap` can be `{ISO}-{level}` or `{ISO}|{subset}-{level}`.
200
201
  For example, `se-4` will show Swedish counties, while `se|03-7` will show municipalities (`se-7`) starting with `03`.
@@ -203,6 +204,10 @@ For example, `se-4` will show Swedish counties, while `se|03-7` will show munici
203
204
 
204
205
  _ Inherits from Map _
205
206
 
207
+ **BubbleMap**
208
+
209
+ _ Inherits from Map _
210
+
206
211
  **ProgressChart**
207
212
 
208
213
  **RangePlot**
@@ -247,6 +252,16 @@ Roadmap
247
252
  Changelog
248
253
  ---------
249
254
 
255
+ - 1.61.1
256
+
257
+ - Improved handling of label_placement = "outside" in SerialChart
258
+
259
+ - 1.61.0
260
+
261
+ - Added non-binned color ramp support to ChoroplethMap, with `use_bins=False`
262
+ - Improved data validation in ChoroplethMap
263
+ - Put largest value on top in choropleth map legends
264
+
250
265
  - 1.60.1
251
266
 
252
267
  - Don't require fiona. Geopandas now support Pyogrio
@@ -1,14 +1,14 @@
1
- newsworthycharts/__init__.py,sha256=4ncjyqowiBpTm3mvedckG9MB2y2Rzc4y2I-5_mVFgeU,1160
1
+ newsworthycharts/__init__.py,sha256=UtUks101pRHa3vCOHg4UPZbyoH12L711yi8xRgqF1aY,1160
2
2
  newsworthycharts/bubblemap.py,sha256=nkocWmpiFgfjEuJGAsthjY5X7Q56jXWsZHUGXw4PwgE,2587
3
3
  newsworthycharts/categoricalchart.py,sha256=LwOZ3VbNy9vzvoK0s77AkbfMt4CXVDSAhnsnBInUIrE,14764
4
- newsworthycharts/chart.py,sha256=VXEJe_g_KahyiUXqXnM3vDS7SQoW1Ppktcj13-A2_oc,30631
5
- newsworthycharts/choroplethmap.py,sha256=dVRShxjkBKa57r_Kp6ysdNCXGwXh3eZK28MvVtLe7BQ,6677
4
+ newsworthycharts/chart.py,sha256=LYrcWNq2zQY90TB1b7e-5XPyBJ2nUGkzHqip1hGm5G0,30682
5
+ newsworthycharts/choroplethmap.py,sha256=bCLf4kcchp1C2djg5AxcOM8BdbaMj0xg7UHrZsDafhI,8013
6
6
  newsworthycharts/datawrapper.py,sha256=RRkAVTpfP4updKxUIBaSmKuBi2RUVPaBRF8HDQhlGGA,11250
7
- newsworthycharts/map.py,sha256=EMpsbvY4V4Y5_ky0Urg4WgvqSEKiDd2kUHXFReMRbb0,6004
7
+ newsworthycharts/map.py,sha256=c409jEO4L8Yr780sJRC0RchR44roAlgOUDAkuk1SfRg,6057
8
8
  newsworthycharts/rangeplot.py,sha256=NE1W9TnmlpK6T3RvBJOU3nd73EXqkj17OY9i5zlw_cQ,8366
9
9
  newsworthycharts/scatterplot.py,sha256=6iaMoiZx__Gc-2Hcdw-8Ga5dSonrFo3oexKNmSFuir4,4959
10
10
  newsworthycharts/seasonalchart.py,sha256=rr55yqJUkaYDR9Ik98jes6574oY1U8t8LwoLE3gClW4,1967
11
- newsworthycharts/serialchart.py,sha256=QjXfPepHVUpxeQvXP9S8BnZwUPY2mSc-5RvGIjZvZhU,26386
11
+ newsworthycharts/serialchart.py,sha256=ZgCaFhxwgrNEZZNB3QnrmcWdT9PnYMtORpb_jz4fzW8,26688
12
12
  newsworthycharts/storage.py,sha256=myERhlpvXyExXxUByBq9eW1bWkCyfH9SwTZbsWSyy3Q,4301
13
13
  newsworthycharts/stripechart.py,sha256=9B6PX2MyLuKNQ8W0OGdKbP0-U32kju0K_NHHwwz_J68,1547
14
14
  newsworthycharts/custom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -28,8 +28,8 @@ newsworthycharts/rc/newsworthy,sha256=X0btLNrmk2DRrfOsKj_WCSIgeD6btacEN2tRF_B4m8
28
28
  newsworthycharts/translations/datawrapper_regions.csv,sha256=fzZcQRX6RFMlNNP8mpgfYNdR3Y0QAlQxDXk8FXTaWWI,9214
29
29
  newsworthycharts/translations/regions.py,sha256=Nv1McQjggD4S3JRu82rDMTG3pqUVR13E5-FBpSYbm98,239
30
30
  newsworthycharts/translations/se_municipalities.csv,sha256=br_mm-IvzQtj_W55_ATREhJ97jWnCweBFlDAVY2EBxA,7098
31
- newsworthycharts-1.60.1.dist-info/LICENSE.txt,sha256=Sq6kGICrehbhC_FolNdXf0djKjTpv3YqjFCIYsxdQN4,1069
32
- newsworthycharts-1.60.1.dist-info/METADATA,sha256=JIG6aIDf814dmnAg3XYbfGmlsSnN2_KeJCngrP4K8Ow,28235
33
- newsworthycharts-1.60.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
34
- newsworthycharts-1.60.1.dist-info/top_level.txt,sha256=dn_kzIj8UgUCMsh1PHdVEQJHVGSsN7Z8YJF-8xXa8n0,17
35
- newsworthycharts-1.60.1.dist-info/RECORD,,
31
+ newsworthycharts-1.61.1.dist-info/LICENSE.txt,sha256=Sq6kGICrehbhC_FolNdXf0djKjTpv3YqjFCIYsxdQN4,1069
32
+ newsworthycharts-1.61.1.dist-info/METADATA,sha256=9aeZ4y_rdYwGMbukHpQ6y1LaIMuyh9zX7NRg7FGqV8I,28644
33
+ newsworthycharts-1.61.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
34
+ newsworthycharts-1.61.1.dist-info/top_level.txt,sha256=dn_kzIj8UgUCMsh1PHdVEQJHVGSsN7Z8YJF-8xXa8n0,17
35
+ newsworthycharts-1.61.1.dist-info/RECORD,,