newsworthycharts 1.65.4__tar.gz → 1.67.0__tar.gz

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.
Files changed (51) hide show
  1. {newsworthycharts-1.65.4/newsworthycharts.egg-info → newsworthycharts-1.67.0}/PKG-INFO +14 -2
  2. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/README.rst +12 -0
  3. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/__init__.py +1 -1
  4. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/categoricalchart.py +89 -37
  5. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/chart.py +2 -2
  6. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/lib/datalist.py +5 -0
  7. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0/newsworthycharts.egg-info}/PKG-INFO +14 -2
  8. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/LICENSE.txt +0 -0
  9. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/MANIFEST.in +0 -0
  10. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/bubblemap.py +0 -0
  11. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/choroplethmap.py +0 -0
  12. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/custom/__init__.py +0 -0
  13. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/custom/climate_cars.py +0 -0
  14. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/datawrapper.py +0 -0
  15. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/lib/__init__.py +0 -0
  16. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/lib/color_fn.py +0 -0
  17. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/lib/colors.py +0 -0
  18. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/lib/formatter.py +0 -0
  19. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/lib/geography.py +0 -0
  20. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/lib/locator.py +0 -0
  21. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/lib/mimetypes.py +0 -0
  22. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/lib/utils.py +0 -0
  23. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/map.py +0 -0
  24. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/maps/se-4.gpkg +0 -0
  25. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/maps/se-7.gpkg +0 -0
  26. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/rangeplot.py +0 -0
  27. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/rc/newsworthy +0 -0
  28. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/scatterplot.py +0 -0
  29. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/seasonalchart.py +0 -0
  30. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/serialchart.py +0 -0
  31. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/storage.py +0 -0
  32. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/stripechart.py +0 -0
  33. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/translations/datawrapper_regions.csv +0 -0
  34. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/translations/regions.py +0 -0
  35. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts/translations/se_municipalities.csv +0 -0
  36. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts.egg-info/SOURCES.txt +0 -0
  37. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts.egg-info/dependency_links.txt +0 -0
  38. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts.egg-info/not-zip-safe +0 -0
  39. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts.egg-info/requires.txt +0 -0
  40. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/newsworthycharts.egg-info/top_level.txt +0 -0
  41. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/setup.cfg +0 -0
  42. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/setup.py +0 -0
  43. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/test/test_categorical_chart.py +0 -0
  44. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/test/test_choropleth_maps.py +0 -0
  45. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/test/test_custom_climate_cars.py +0 -0
  46. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/test/test_data_list.py +0 -0
  47. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/test/test_datawrapper.py +0 -0
  48. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/test/test_main.py +0 -0
  49. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/test/test_rangeplot.py +0 -0
  50. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/test/test_scatterplot.py +0 -0
  51. {newsworthycharts-1.65.4 → newsworthycharts-1.67.0}/test/test_serial_chart.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: newsworthycharts
3
- Version: 1.65.4
3
+ Version: 1.67.0
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.65.4.tar.gz
6
+ Download-URL: https://github.com/jplusplus/newsworthycharts/archive/1.67.0.tar.gz
7
7
  Author: Jens Finnäs and Leo Wallentin, J++ Stockholm
8
8
  Author-email: stockholm@jplusplus.org
9
9
  License: MIT
@@ -259,6 +259,18 @@ Roadmap
259
259
  Changelog
260
260
  ---------
261
261
 
262
+ - 1.67.0
263
+
264
+ - Fixed label margins in pie charts
265
+ - Trim all titles and subtitles of leading and trailing whitespace
266
+ - Improved piechart annotation
267
+ - Support `label_placement` (legend|outside|inline) in categorical charts ('legend' is still buggy in pie charts)
268
+
269
+ - 1.66.0
270
+
271
+ - Support multiple data series in pie charts (displayed as small multiples)
272
+
273
+
262
274
  - 1.65.4
263
275
 
264
276
  - Revert some of the title margin changes
@@ -232,6 +232,18 @@ Roadmap
232
232
  Changelog
233
233
  ---------
234
234
 
235
+ - 1.67.0
236
+
237
+ - Fixed label margins in pie charts
238
+ - Trim all titles and subtitles of leading and trailing whitespace
239
+ - Improved piechart annotation
240
+ - Support `label_placement` (legend|outside|inline) in categorical charts ('legend' is still buggy in pie charts)
241
+
242
+ - 1.66.0
243
+
244
+ - Support multiple data series in pie charts (displayed as small multiples)
245
+
246
+
235
247
  - 1.65.4
236
248
 
237
249
  - Revert some of the title margin changes
@@ -1,4 +1,4 @@
1
- __version__ = "1.65.4"
1
+ __version__ = "1.67.0"
2
2
 
3
3
  from .chart import Chart
4
4
  from .choroplethmap import ChoroplethMap
@@ -1,6 +1,6 @@
1
1
  from .chart import Chart
2
2
  from .lib.utils import to_float
3
-
3
+ from adjustText import adjust_text
4
4
  import numpy as np
5
5
 
6
6
 
@@ -16,6 +16,7 @@ class CategoricalChart(Chart):
16
16
  self.stacked = False
17
17
  self.legend = True
18
18
  self.type = "bars"
19
+ self.label_placement = None # legend|inline|outside # defaults will vary
19
20
 
20
21
  # Optional: specify a list of colors (for multiple datasets)
21
22
  self.colors = None
@@ -25,32 +26,49 @@ class CategoricalChart(Chart):
25
26
  return self.stacked
26
27
 
27
28
  def _add_pie_data(self):
28
- if len(self.data) > 1:
29
- raise ValueError("Pie chart takes one data series only.")
30
- self.legend = False
31
29
  self.show_ticks = False
32
30
 
33
- data = self.data[0]
34
- values = [to_float(x[1]) for x in data]
35
- labels = [x[0] for x in data]
36
-
37
- if self.colors is not None:
38
- colors = self.colors
39
- else:
40
- colors = [self._nwc_style["qualitative_colors"][i] for i in range(len(values))]
41
-
42
- explode = [0.1 if x == self.highlight else 0 for x in labels]
31
+ if len(self.data) > 1:
32
+ subaxes = self._fig.subplots(1, len(self.data))
33
+ patches = []
34
+ for idx, serie in enumerate(self.data):
35
+ if len(self.data) == 1:
36
+ subax = self.ax
37
+ else:
38
+ subax = subaxes[idx]
43
39
 
44
- self.ax.pie(
45
- values,
46
- labels=labels,
47
- startangle=90,
48
- colors=colors,
49
- explode=explode
50
- )
51
- self.ax.axis('equal')
40
+ values = [to_float(x[1]) for x in serie]
41
+ labels = [x[0] for x in serie]
52
42
 
53
- self._setup_legend()
43
+ if self.colors is not None:
44
+ colors = self.colors
45
+ else:
46
+ colors = [self._nwc_style["qualitative_colors"][i] for i in range(len(values))]
47
+
48
+ explode = [0.1 if x == self.highlight else 0 for x in labels]
49
+ legend_placement = self.label_placement or "inline"
50
+ _pie = subax.pie(
51
+ values,
52
+ labels=labels if legend_placement == "inline" else None,
53
+ startangle=90,
54
+ colors=colors,
55
+ explode=explode
56
+ )
57
+ if idx == 0:
58
+ patches += _pie[0]
59
+ subax.axis('equal')
60
+ # `labels` in pie charts are used to label the series, not the values
61
+ if self.labels:
62
+ subax.set_title(self.labels[idx], loc='center', y=0)
63
+ if legend_placement == "inline":
64
+ self.legend = False
65
+ elif legend_placement == "legend":
66
+ self.ax.legend(patches, labels, loc='best', frameon=True, fancybox=True).set_zorder(100)
67
+ elif legend_placement == "outside":
68
+ _ = self.ax.legend(patches, labels, bbox_to_anchor=(1.04, 1), loc="upper left")
69
+ _.set(zorder=20)
70
+
71
+ self.ax.axis('off')
54
72
 
55
73
  def _add_data(self):
56
74
  if self.type == "pie":
@@ -84,7 +102,7 @@ class CategoricalChart(Chart):
84
102
  serie_values.append(_values)
85
103
 
86
104
  cum_values = np.cumsum(serie_values, axis=0).tolist()
87
-
105
+ self._bars = []
88
106
  for i, data in enumerate(self.data):
89
107
 
90
108
  # Replace None values with 0's to be able to plot bars
@@ -160,6 +178,7 @@ class CategoricalChart(Chart):
160
178
  bar_pos = [x + i * bar_width
161
179
  for x in np.arange(len(values))]
162
180
 
181
+ _bar = None
163
182
  if self.bar_orientation == "horizontal":
164
183
  kwargs = dict(align='center', height=bar_width,
165
184
  color=colors, zorder=2)
@@ -167,7 +186,7 @@ class CategoricalChart(Chart):
167
186
  # To make stacked bars we need to set bottom value
168
187
  kwargs["left"] = cum_values[i - 1]
169
188
 
170
- self.ax.barh(bar_pos, values, **kwargs)
189
+ _bar = self.ax.barh(bar_pos, values, **kwargs)
171
190
 
172
191
  elif self.bar_orientation == "vertical":
173
192
  kwargs = dict(
@@ -178,7 +197,8 @@ class CategoricalChart(Chart):
178
197
  if self.stacked and i > 0:
179
198
  # To make stacked bars we need to set bottom value
180
199
  kwargs["bottom"] = cum_values[i - 1]
181
- self.ax.bar(bar_pos, values, **kwargs)
200
+ _bar = self.ax.bar(bar_pos, values, **kwargs)
201
+ self._bars.append(_bar)
182
202
 
183
203
  if self.bar_orientation == "horizontal":
184
204
  margin = 0.02 # above and below first/last bar on horizontal
@@ -200,9 +220,6 @@ class CategoricalChart(Chart):
200
220
  self.ax.set_xticklabels(categories)
201
221
  self.ax.xaxis.set_ticks_position('none')
202
222
 
203
- if len(self.data) > 1:
204
- self.ax.legend(self.labels, loc='best')
205
-
206
223
  self._setup_legend()
207
224
 
208
225
  def _setup_legend(self):
@@ -211,6 +228,31 @@ class CategoricalChart(Chart):
211
228
  legend = self.ax.get_legend()
212
229
  if legend:
213
230
  legend.remove()
231
+ else:
232
+ if len(self.data) == 0 and self.type != "pie":
233
+ return
234
+ placement = self.label_placement or "legend"
235
+ if placement == "legend":
236
+ self.ax.legend(self.labels, loc='best')
237
+ elif placement == "outside":
238
+ _ = self.ax.legend(self.labels, bbox_to_anchor=(1.04, 1), loc="upper left")
239
+ _.set(zorder=20)
240
+ elif placement == "inline":
241
+ texts = []
242
+ for idx, _bar in enumerate(self._bars):
243
+ _texts = self.ax.bar_label(
244
+ _bar,
245
+ labels=[self.labels[idx]] * self.data.num_categories,
246
+ label_type="center",
247
+ backgroundcolor="#f0f0f099",
248
+ )
249
+ if idx > 0:
250
+ texts += [*_texts]
251
+ adjust_text(
252
+ texts,
253
+ ax=self.ax,
254
+ autoalign="x" if self.bar_orientation == "horizontal" else "y",
255
+ )
214
256
 
215
257
 
216
258
  class CategoricalChartWithReference(CategoricalChart):
@@ -236,6 +278,7 @@ class CategoricalChartWithReference(CategoricalChart):
236
278
  self.value_axis.grid(True)
237
279
 
238
280
  bar_width = 0.8 / len(self.data)
281
+ self._bars = []
239
282
  for i, data in enumerate(self.data):
240
283
 
241
284
  # Replace None values with 0's to be able to plot bars
@@ -263,18 +306,30 @@ class CategoricalChartWithReference(CategoricalChart):
263
306
 
264
307
  zorder = len(self.data) - i
265
308
  if self.bar_orientation == "horizontal":
266
- self.ax.barh(bar_pos, values, height=bar_width, align='center',
267
- color=color, zorder=zorder)
309
+ bar = self.ax.barh(
310
+ bar_pos,
311
+ values,
312
+ height=bar_width,
313
+ align='center',
314
+ color=color,
315
+ zorder=zorder,
316
+ )
268
317
  self.ax.set_yticks(tick_pos)
269
318
  self.ax.set_yticklabels(categories)
270
319
  # self.ax.invert_yaxis()
271
320
 
272
321
  elif self.bar_orientation == "vertical":
273
- self.ax.bar(bar_pos, values, width=bar_width, color=color,
274
- zorder=zorder)
322
+ bar = self.ax.bar(
323
+ bar_pos,
324
+ values,
325
+ width=bar_width,
326
+ color=color,
327
+ zorder=zorder,
328
+ )
275
329
  self.ax.set_xticks(tick_pos)
276
330
  self.ax.set_xticklabels(categories)
277
331
  self.ax.xaxis.set_ticks_position('none')
332
+ self._bars.append(bar)
278
333
 
279
334
  # Make sure labels are not cropped
280
335
  yaxis_bbox = self.ax.yaxis.get_tightbbox(self._fig.canvas.get_renderer())
@@ -282,9 +337,6 @@ class CategoricalChartWithReference(CategoricalChart):
282
337
  margin -= yaxis_bbox.min[0] / float(self._w)
283
338
  self._fig.subplots_adjust(left=margin)
284
339
 
285
- if self.labels:
286
- self.ax.legend(self.labels, loc='best')
287
-
288
340
  self._setup_legend()
289
341
 
290
342
 
@@ -339,7 +391,7 @@ class ProgressChart(CategoricalChart):
339
391
 
340
392
  # rect.set_linewidth(1)
341
393
  # rect.set_edgecolor(color_progress)
342
-
394
+
343
395
  # LABELING: Target
344
396
  if self.target_label:
345
397
  offset = 25
@@ -285,7 +285,7 @@ class Chart(object):
285
285
  def _add_title(self, title_text):
286
286
  """Add a title."""
287
287
  text = self._fig.suptitle(
288
- title_text, wrap=True,
288
+ title_text.strip(), wrap=True,
289
289
  x=0,
290
290
  y=0.985, # default: 0.98
291
291
  horizontalalignment="left",
@@ -300,7 +300,7 @@ class Chart(object):
300
300
  text = self._fig.text(
301
301
  0,
302
302
  y_pos,
303
- subtitle_text,
303
+ subtitle_text.strip(),
304
304
  wrap=True,
305
305
  verticalalignment="top",
306
306
  linespacing=1.4,
@@ -196,6 +196,11 @@ class DataSet(MutableSequence):
196
196
  values = array(self.values, dtype=float)
197
197
  return np.nansum(values, axis=0).tolist()
198
198
 
199
+ @property
200
+ def num_categories(self):
201
+ categories = set([x[0] for s in self.list for x in s])
202
+ return len(categories)
203
+
199
204
  def __len__(self):
200
205
  return len(self.list)
201
206
 
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: newsworthycharts
3
- Version: 1.65.4
3
+ Version: 1.67.0
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.65.4.tar.gz
6
+ Download-URL: https://github.com/jplusplus/newsworthycharts/archive/1.67.0.tar.gz
7
7
  Author: Jens Finnäs and Leo Wallentin, J++ Stockholm
8
8
  Author-email: stockholm@jplusplus.org
9
9
  License: MIT
@@ -259,6 +259,18 @@ Roadmap
259
259
  Changelog
260
260
  ---------
261
261
 
262
+ - 1.67.0
263
+
264
+ - Fixed label margins in pie charts
265
+ - Trim all titles and subtitles of leading and trailing whitespace
266
+ - Improved piechart annotation
267
+ - Support `label_placement` (legend|outside|inline) in categorical charts ('legend' is still buggy in pie charts)
268
+
269
+ - 1.66.0
270
+
271
+ - Support multiple data series in pie charts (displayed as small multiples)
272
+
273
+
262
274
  - 1.65.4
263
275
 
264
276
  - Revert some of the title margin changes