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.
- newsworthycharts/__init__.py +1 -1
- newsworthycharts/chart.py +2 -2
- newsworthycharts/choroplethmap.py +31 -8
- newsworthycharts/map.py +1 -0
- newsworthycharts/serialchart.py +7 -2
- {newsworthycharts-1.60.1.dist-info → newsworthycharts-1.61.1.dist-info}/METADATA +27 -12
- {newsworthycharts-1.60.1.dist-info → newsworthycharts-1.61.1.dist-info}/RECORD +10 -10
- {newsworthycharts-1.60.1.dist-info → newsworthycharts-1.61.1.dist-info}/LICENSE.txt +0 -0
- {newsworthycharts-1.60.1.dist-info → newsworthycharts-1.61.1.dist-info}/WHEEL +0 -0
- {newsworthycharts-1.60.1.dist-info → newsworthycharts-1.61.1.dist-info}/top_level.txt +0 -0
newsworthycharts/__init__.py
CHANGED
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
|
-
|
175
|
-
|
176
|
-
|
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
|
newsworthycharts/serialchart.py
CHANGED
@@ -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
|
-
|
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.
|
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.
|
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
|
24
|
+
Requires-Dist: geopandas >=1
|
25
25
|
Requires-Dist: mapclassify ==2.6.1
|
26
|
-
Requires-Dist:
|
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
|
-
-
|
192
|
-
-
|
193
|
-
-
|
194
|
-
-
|
195
|
-
-
|
196
|
-
-
|
197
|
-
-
|
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=
|
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=
|
5
|
-
newsworthycharts/choroplethmap.py,sha256=
|
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=
|
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=
|
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.
|
32
|
-
newsworthycharts-1.
|
33
|
-
newsworthycharts-1.
|
34
|
-
newsworthycharts-1.
|
35
|
-
newsworthycharts-1.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|