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.
- newsworthycharts/__init__.py +1 -1
- newsworthycharts/categoricalchart.py +32 -0
- newsworthycharts/chart.py +26 -19
- newsworthycharts/lib/datalist.py +13 -0
- {newsworthycharts-1.63.4.dist-info → newsworthycharts-1.64.0.dist-info}/METADATA +22 -6
- {newsworthycharts-1.63.4.dist-info → newsworthycharts-1.64.0.dist-info}/RECORD +9 -9
- {newsworthycharts-1.63.4.dist-info → newsworthycharts-1.64.0.dist-info}/LICENSE.txt +0 -0
- {newsworthycharts-1.63.4.dist-info → newsworthycharts-1.64.0.dist-info}/WHEEL +0 -0
- {newsworthycharts-1.63.4.dist-info → newsworthycharts-1.64.0.dist-info}/top_level.txt +0 -0
newsworthycharts/__init__.py
CHANGED
@@ -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(
|
142
|
-
|
143
|
-
|
144
|
-
|
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) >
|
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
|
-
|
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
|
-
|
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
|
-
|
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"])
|
newsworthycharts/lib/datalist.py
CHANGED
@@ -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.
|
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.
|
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
|
-
-
|
185
|
+
- bar_orientation = "horizontal" # [horizontal|vertical]
|
186
|
+
- colors = None # A dictionary of colors
|
185
187
|
- legend = True
|
186
|
-
-
|
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=
|
1
|
+
newsworthycharts/__init__.py,sha256=Ar8KT2Z_t3lWJ367gTYTFtMKii3FmyxKPDhlK3qrz2s,1160
|
2
2
|
newsworthycharts/bubblemap.py,sha256=nkocWmpiFgfjEuJGAsthjY5X7Q56jXWsZHUGXw4PwgE,2587
|
3
|
-
newsworthycharts/categoricalchart.py,sha256=
|
4
|
-
newsworthycharts/chart.py,sha256=
|
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=
|
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.
|
32
|
-
newsworthycharts-1.
|
33
|
-
newsworthycharts-1.
|
34
|
-
newsworthycharts-1.
|
35
|
-
newsworthycharts-1.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|