newsworthycharts 1.63.4__py3-none-any.whl → 1.64.0__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.63.4"
1
+ __version__ = "1.64.0"
2
2
 
3
3
  from .chart import Chart
4
4
  from .choroplethmap import ChoroplethMap
@@ -15,11 +15,43 @@ class CategoricalChart(Chart):
15
15
  self.annotation_rotation = 0
16
16
  self.stacked = False
17
17
  self.legend = True
18
+ self.type = "bars"
18
19
 
19
20
  # Optional: specify a list of colors (for multiple datasets)
20
21
  self.colors = None
21
22
 
23
+ def _add_pie_data(self):
24
+ if len(self.data) > 1:
25
+ raise ValueError("Pie chart takes one data series only.")
26
+ self.legend = False
27
+ self.show_ticks = False
28
+
29
+ data = self.data[0]
30
+ values = [to_float(x[1]) for x in data]
31
+ labels = [x[0] for x in data]
32
+
33
+ if self.colors is not None:
34
+ colors = self.colors
35
+ else:
36
+ colors = [self._nwc_style["qualitative_colors"][i] for i in range(len(values))]
37
+
38
+ explode = [0.1 if x == self.highlight else 0 for x in labels]
39
+
40
+ self.ax.pie(
41
+ values,
42
+ labels=labels,
43
+ startangle=90,
44
+ colors=colors,
45
+ explode=explode
46
+ )
47
+ self.ax.axis('equal')
48
+
49
+ self._setup_legend()
50
+
22
51
  def _add_data(self):
52
+ if self.type == "pie":
53
+ self._add_pie_data()
54
+ return
23
55
  allowed_orientations = ["horizontal", "vertical"]
24
56
  if self.bar_orientation not in allowed_orientations:
25
57
  raise ValueError(f"Valid oriantations: {allowed_orientations}")
newsworthycharts/chart.py CHANGED
@@ -138,10 +138,12 @@ class Chart(object):
138
138
  return self._get_formatter(self.units)
139
139
 
140
140
  def _get_formatter(self, units):
141
- formatter = Formatter(self._language,
142
- decimals=self.decimals,
143
- force_decimals=self.force_decimals,
144
- scale="celsius")
141
+ formatter = Formatter(
142
+ self._language,
143
+ decimals=self.decimals,
144
+ force_decimals=self.force_decimals,
145
+ scale="celsius",
146
+ )
145
147
  if units == "percent":
146
148
  return FuncFormatter(formatter.percent)
147
149
  elif units == "degrees":
@@ -396,7 +398,7 @@ class Chart(object):
396
398
  d = num2date(x).isoformat()[:10]
397
399
  # 9 years later
398
400
  d2 = str(int(d[:4]) + 9) + d[4:]
399
- if len(self.data.x_points) > 7:
401
+ if len(self.data.x_points) > 5:
400
402
  return formatter.date(d, "yy") + "–" + formatter.date(d2, "yy")
401
403
  else:
402
404
  return formatter.date(d, "y") + "–" + formatter.date(d2, "yy")
@@ -522,25 +524,30 @@ class Chart(object):
522
524
  if try_dec > 2:
523
525
  keep_trying = False
524
526
  try_dec += 1
525
- # Remove duplicate y ticks (most should be gone as per above)
527
+
526
528
  ticks = self.value_axis.get_ticklabels()
527
529
  ticks_ = [x for (i, x) in enumerate(ticks) if ticks[i - 1].get_text() != x.get_text()]
528
- if len(ticks_) < len(ticks):
529
- y = [float(x._y) for x in ticks_]
530
- if self.decimals == 0:
531
- # Recrate with integres
532
- import math
533
- _bottom = min(y)
534
- _top = math.ceil(max(y))
535
- _bottom, _top = int(_bottom), int(_top)
536
- y = range(_bottom, _top + 1)
537
- y = [float(x) for x in y]
538
- self.value_axis.set_ticks(y)
530
+ # remove non integer ticks
539
531
  if self.decimals == 0:
540
- # remove non integer ticks
541
532
  y = [float(x._y) for x in ticks]
542
- y = [x for x in y if x.is_integer()]
533
+ if self.units == "percent":
534
+ y = [x for x in y if (x * 100).is_integer()]
535
+ else:
536
+ y = [x for x in y if x.is_integer()]
543
537
  self.value_axis.set_ticks(y)
538
+ # Remove duplicate y ticks (most should be gone as per above)
539
+ elif len(ticks_) == 2 and self.data:
540
+ # When only two ticks we want them on top and bottom
541
+ self.value_axis.set_ticks([float(ticks[0]._y), self.data.max_val])
542
+ elif len(ticks_) < len(ticks):
543
+ y = [float(x._y) for x in ticks_]
544
+ self.value_axis.set_ticks(y)
545
+
546
+ # Force a second tick if we ended up having just one
547
+ ticks = self.value_axis.get_ticklabels()
548
+ ticks_ = [x for (i, x) in enumerate(ticks) if ticks[i - 1].get_text() != x.get_text()]
549
+ if len(ticks_) <= 1 and self.data:
550
+ self.value_axis.set_ticks([0, self.data.max_val])
544
551
 
545
552
  for a in self.annotations:
546
553
  self._annotate_point(a["text"], a["xy"], a["direction"])
@@ -171,8 +171,19 @@ class DataSet(MutableSequence):
171
171
 
172
172
  def __init__(self, *args):
173
173
  self.list = list()
174
+ self.min_val = inf
175
+ self.max_val = -inf
174
176
  self.extend(list(args))
175
177
 
178
+ def check(self, v):
179
+ # Update metadata with newly added data
180
+ values = [to_float(x[1]) for x in v]
181
+ values = [x for x in values if x is not None]
182
+ if values:
183
+ self.min_val = min(self.min_val, min(values))
184
+ self.max_val = max(self.max_val, max(values))
185
+ return v
186
+
176
187
  def __len__(self):
177
188
  return len(self.list)
178
189
 
@@ -183,9 +194,11 @@ class DataSet(MutableSequence):
183
194
  del self.list[i]
184
195
 
185
196
  def __setitem__(self, i, v):
197
+ v = self.check(v)
186
198
  self.list[i] = v
187
199
 
188
200
  def insert(self, i, v):
201
+ v = self.check(v)
189
202
  self.list.insert(i, v)
190
203
 
191
204
  def __str__(self):
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: newsworthycharts
3
- Version: 1.63.4
3
+ Version: 1.64.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.63.4.tar.gz
6
+ Download-URL: https://github.com/jplusplus/newsworthycharts/archive/1.64.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
@@ -154,7 +154,7 @@ These settings are available for all chart types:
154
154
 
155
155
  **SerialChart**
156
156
 
157
- - type = 'line' # line|bars
157
+ - type = 'line' # line|bars, or a list of types for each data serie
158
158
  - bar_width = 0.9 # percent of data point width
159
159
  - allow_broken_y_axis = True|False # default depends on chart type
160
160
  - baseline = 0 # The “zero” line. Useful for plotting deviations, e.g. temperatures above/below mean
@@ -173,17 +173,20 @@ These settings are available for all chart types:
173
173
 
174
174
  **SeasonalChart**
175
175
 
176
+ _ Inherits from SerialChart _
177
+
176
178
  **BubbleMap**
177
179
 
178
180
  - bubble_size = 1 # The size of the bubbles
179
181
 
180
182
  **CategoricalChart**
181
183
 
182
- - bar_orientation = "horizontal" # [horizontal|vertical]
183
184
  - annotation_rotation = 0
184
- - stacked = False
185
+ - bar_orientation = "horizontal" # [horizontal|vertical]
186
+ - colors = None # A dictionary of colors
185
187
  - legend = True
186
- - colors = None
188
+ - stacked = False
189
+ - type = "bars" # [bars|pie]
187
190
 
188
191
  **CategoricalChartWithReference**
189
192
 
@@ -252,6 +255,19 @@ Roadmap
252
255
  Changelog
253
256
  ---------
254
257
 
258
+ - 1.64.0
259
+
260
+ - Improved handling of value axis in categorical charts
261
+ - Make sure at least one value axis tick is always printed
262
+ - Experimental support for simple, single series pie charts in CategoricalChart
263
+ - Fixed bug introduced in 1.63.3, where `decimals` and `units: percent` would not work together
264
+ - Fixed weird edge case when ticks would be offset for small numbers
265
+
266
+ - 1.63.5
267
+
268
+ - Improved edge case handling when using fixed decimal places and remove duplicated ticks
269
+ - Tighter x-axis ticks in decennial data
270
+
255
271
  - 1.63.4
256
272
 
257
273
  - Fixed edge case in integer check
@@ -1,7 +1,7 @@
1
- newsworthycharts/__init__.py,sha256=Y4F1H2k7Q3k6WNKCJmjcTRDKa8hK6_hUhba1GnqZJuI,1160
1
+ newsworthycharts/__init__.py,sha256=Ar8KT2Z_t3lWJ367gTYTFtMKii3FmyxKPDhlK3qrz2s,1160
2
2
  newsworthycharts/bubblemap.py,sha256=nkocWmpiFgfjEuJGAsthjY5X7Q56jXWsZHUGXw4PwgE,2587
3
- newsworthycharts/categoricalchart.py,sha256=LwOZ3VbNy9vzvoK0s77AkbfMt4CXVDSAhnsnBInUIrE,14764
4
- newsworthycharts/chart.py,sha256=dUh32lZ0OZhcKCf61BvqFcRAHAV7Wc9ob8Lt1jXSuhE,32558
3
+ newsworthycharts/categoricalchart.py,sha256=4qzx17QcJX-Xw7COwyL_atIEgeVkNnlgS3B1v4-Q6dQ,15648
4
+ newsworthycharts/chart.py,sha256=5JqEsWZUNefgXyhpznXcV5U1j-IOScsGWQoCijVMo9c,32841
5
5
  newsworthycharts/choroplethmap.py,sha256=bCLf4kcchp1C2djg5AxcOM8BdbaMj0xg7UHrZsDafhI,8013
6
6
  newsworthycharts/datawrapper.py,sha256=RRkAVTpfP4updKxUIBaSmKuBi2RUVPaBRF8HDQhlGGA,11250
7
7
  newsworthycharts/map.py,sha256=c409jEO4L8Yr780sJRC0RchR44roAlgOUDAkuk1SfRg,6057
@@ -16,7 +16,7 @@ newsworthycharts/custom/climate_cars.py,sha256=WyNLgjgRCv_zRrzVuk_BmcigFSzpzudjE
16
16
  newsworthycharts/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  newsworthycharts/lib/color_fn.py,sha256=ck65GzTS9oPgHUCnKDwX2z8zlnNyzncw97MmhXwi8z8,1282
18
18
  newsworthycharts/lib/colors.py,sha256=U04TDkvoMQkcldRFXfnwyLOTwq1SWW2se-Ad-DNcw9o,485
19
- newsworthycharts/lib/datalist.py,sha256=fsO_esZBt4Aw_4n_l2LuswAYArbM-8Z8G9DAXo1oVZU,5376
19
+ newsworthycharts/lib/datalist.py,sha256=Lmb37IXZi9fqrV4qAZRFDtH4ctMDpOqH-ITV62mfarQ,5807
20
20
  newsworthycharts/lib/formatter.py,sha256=GNH43hE0bC17OgiV8LYH3YUrEhm7OJh9XzfSV4HVtHo,4838
21
21
  newsworthycharts/lib/geography.py,sha256=K0_teFmuPJwXX7Py-amJB_1YY5_gL2kBYhz1LrRCyTg,584
22
22
  newsworthycharts/lib/locator.py,sha256=rJHdgiA0LASRzdLINhTeU5zOoq1TCMgge4KOBWSagnM,3041
@@ -28,8 +28,8 @@ newsworthycharts/rc/newsworthy,sha256=vbYTav1w3DmB5tpaaV7Xl5q7TQJsc9eou6pLCoWc2v
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.63.4.dist-info/LICENSE.txt,sha256=Sq6kGICrehbhC_FolNdXf0djKjTpv3YqjFCIYsxdQN4,1069
32
- newsworthycharts-1.63.4.dist-info/METADATA,sha256=kxlCxLX3F38SdbYVz7LDAli8uQNQRVMjz4Qti0GM-yU,29572
33
- newsworthycharts-1.63.4.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
34
- newsworthycharts-1.63.4.dist-info/top_level.txt,sha256=dn_kzIj8UgUCMsh1PHdVEQJHVGSsN7Z8YJF-8xXa8n0,17
35
- newsworthycharts-1.63.4.dist-info/RECORD,,
31
+ newsworthycharts-1.64.0.dist-info/LICENSE.txt,sha256=Sq6kGICrehbhC_FolNdXf0djKjTpv3YqjFCIYsxdQN4,1069
32
+ newsworthycharts-1.64.0.dist-info/METADATA,sha256=Bd6gWjBOcSYe5uGZju_Ohtt_lqmkd1I_KOjsTzyFpZs,30226
33
+ newsworthycharts-1.64.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
34
+ newsworthycharts-1.64.0.dist-info/top_level.txt,sha256=dn_kzIj8UgUCMsh1PHdVEQJHVGSsN7Z8YJF-8xXa8n0,17
35
+ newsworthycharts-1.64.0.dist-info/RECORD,,