toolsos 0.2.7__py3-none-any.whl → 0.3.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.
toolsos/geo.py CHANGED
@@ -1,7 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from pathlib import Path
3
4
  from typing import Any, Union
4
5
 
6
+ import geopandas as gpd
7
+ import pandas as pd
5
8
  import requests
6
9
 
7
10
 
@@ -43,6 +46,38 @@ def get_geo_json(
43
46
  return json
44
47
 
45
48
 
49
+ def get_geo_dataframe(
50
+ level: str,
51
+ year: Union[int, Any],
52
+ with_water: bool = False,
53
+ mra: bool = False,
54
+ from_crs=4326,
55
+ to_crs=28992,
56
+ ):
57
+
58
+ gdf = gpd.GeoDataFrame.from_features(
59
+ get_geo_json(level=level, year=year, with_water=with_water, mra=mra)
60
+ )
61
+
62
+ gdf = gdf.set_crs(from_crs).to_crs(to_crs)
63
+
64
+ return gdf
65
+
66
+
67
+ def merge_data_to_gdf(
68
+ data: str, gdf: gpd.GeoDataFrame, key_data: str = "code", key_gdf: str = "code"
69
+ ) -> gpd.GeoDataFrame:
70
+ p = Path(data)
71
+ if p.suffix == ".csv":
72
+ df = pd.read_csv(data)
73
+ elif p.suffix in [".xlsx", ".xls"]:
74
+ df = pd.read_excel(data)
75
+ else:
76
+ raise ValueError(f"File type not supported: {p.suffix}")
77
+
78
+ return gdf.merge(df, how="left", left_on=key_data, right_on=key_gdf)
79
+
80
+
46
81
  def extract_name_code_table(geo_json: dict[str, str]) -> dict[str, str]:
47
82
  """_summary_
48
83
 
toolsos/helpers.py CHANGED
@@ -24,16 +24,29 @@ def os_cut(
24
24
  start_label: str = "lager dan",
25
25
  end_label: str = "en hoger",
26
26
  add_edge: Optional[int] = None,
27
- sep: str = " - ",
27
+ sep: str = " tot ",
28
+ na_value: Optional[str] = None,
29
+ unit: Optional[str] = None,
28
30
  ) -> pd.Series:
29
31
  # Add non_overlap to left edge/boundary
30
32
  if not add_edge:
31
33
  add_edge = 0
32
34
 
33
- start_l = [f"{start_label} {bins[1]}"]
35
+ if not unit:
36
+ unit = ""
37
+
38
+ start_l = [f"{start_label} {bins[1]}{unit}"]
34
39
  inbetween_labels = [
35
- f"{bins[i] + add_edge}{sep}{bins[i+1]}" for i in range(1, len(bins) - 2)
40
+ f"{bins[i] + add_edge}{unit}{sep}{bins[i+1]}{unit}"
41
+ for i in range(1, len(bins) - 2)
36
42
  ]
37
- end_l = [f"{bins[-2]} {end_label}"]
43
+ end_l = [f"{bins[-2]}{unit} {end_label}"]
44
+
45
+ labels = start_l + inbetween_labels + end_l
46
+
47
+ categorized = pd.cut(x, bins=bins, labels=labels, include_lowest=True) # type: ignore
48
+
49
+ if na_value:
50
+ categorized = categorized.cat.add_categories(na_value).fillna(na_value)
38
51
 
39
- return pd.cut(x, bins=bins, labels=start_l + inbetween_labels + end_l) # type: ignore
52
+ return categorized
@@ -0,0 +1,72 @@
1
+ from typing import Any, Iterable, Optional
2
+
3
+ import geopandas as gpd
4
+ import matplotlib.pyplot as plt
5
+ from matplotlib.colors import ListedColormap
6
+ from matplotlib.patches import Patch
7
+
8
+
9
+ def plot_choropleth(
10
+ gdf: gpd.GeoDataFrame,
11
+ column: str,
12
+ colors: Iterable[str],
13
+ column_label: Optional[str] = False,
14
+ column_label_kwargs: Any = None,
15
+ legend_title: Optional[str] = None,
16
+ edgecolor: str = "grey",
17
+ figsize: tuple[int, int] = (10, 8),
18
+ bbox_to_anchor: tuple[int, int] = (-0.05, 0),
19
+ ):
20
+ # plotten
21
+ fig, ax = plt.subplots(figsize=figsize)
22
+
23
+ gdf.plot(
24
+ column=column,
25
+ cmap=ListedColormap(colors),
26
+ ax=ax,
27
+ categorical=True,
28
+ edgecolor=edgecolor,
29
+ linewidth=0.2,
30
+ )
31
+
32
+ labels = gdf["categorieen"].cat.categories
33
+
34
+ if not column_label_kwargs:
35
+ column_label_kwargs = {}
36
+
37
+ if column_label:
38
+ for x, y, label in zip(
39
+ gdf.geometry.representative_point().x,
40
+ gdf.geometry.representative_point().y,
41
+ gdf[column_label],
42
+ ):
43
+ ax.annotate(
44
+ label,
45
+ xy=(x, y),
46
+ xytext=(0, 0),
47
+ textcoords="offset points",
48
+ **column_label_kwargs,
49
+ )
50
+
51
+ # Create custom legend using the 'colors' and 'labels' variables, with a grey border
52
+ legend_elements = [
53
+ Patch(facecolor=color, label=label, edgecolor="#b0b0b0")
54
+ for color, label in zip(colors, labels)
55
+ ]
56
+
57
+ # Move the legend to the bottom left outside the plot
58
+ ax.legend(
59
+ handles=legend_elements,
60
+ bbox_to_anchor=bbox_to_anchor,
61
+ loc="lower left",
62
+ title=legend_title,
63
+ frameon=False,
64
+ )
65
+
66
+ # lat/lon uit
67
+ ax.set_axis_off()
68
+
69
+ # laten zien
70
+ plt.tight_layout()
71
+
72
+ return fig, ax
@@ -278,7 +278,14 @@ def get_cols_id_with_pattern(df: pd.DataFrame, pattern: str) -> list[int]:
278
278
  Returns:
279
279
  list[int]: list with column indices matching pattern
280
280
  """
281
- return [idx for idx, col in enumerate(df.columns) if re.findall(pattern, col)]
281
+
282
+ if isinstance(df.columns, pd.MultiIndex):
283
+ # Use the lowest level in the multi-index column
284
+ return [
285
+ idx for idx, col in enumerate(df.columns) if re.findall(pattern, col[-1])
286
+ ]
287
+ else:
288
+ return [idx for idx, col in enumerate(df.columns) if re.findall(pattern, col)]
282
289
 
283
290
 
284
291
  def get_string_cols_ids(df: pd.DataFrame) -> list[int]:
@@ -702,6 +709,7 @@ def format_worksheet(
702
709
  "The number of widths defined in column_widths should be equal to the number of columsn in the dataframe"
703
710
  )
704
711
  col_widths = column_widths
712
+
705
713
  elif (autofit_columns == "column_names") or (autofit_columns is None):
706
714
  col_widths = get_max_col_widths(df)
707
715
  elif autofit_columns == "all_data":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: toolsos
3
- Version: 0.2.7
3
+ Version: 0.3.0
4
4
  Summary: OS tools
5
5
  Author-email: OS <d.schmitz@amsterdam.nl>
6
6
  Keywords: tools,Onderzoek & Statistiek
@@ -26,6 +26,7 @@ Requires-Dist: pyreadstat; extra == "all"
26
26
  Requires-Dist: pyyaml; extra == "all"
27
27
  Requires-Dist: requests; extra == "all"
28
28
  Requires-Dist: sqlalchemy; extra == "all"
29
+ Requires-Dist: geopandas; extra == "all"
29
30
 
30
31
  # Tools Onderzoek & Statistiek
31
32
 
@@ -2,8 +2,8 @@ toolsos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  toolsos/cbs_tools.py,sha256=361cogk0aIU4D4BKHaa7YSOBh64t5C3zrHlqtWx0iIc,3465
3
3
  toolsos/create_tables.py,sha256=43FHK3EERjumBtnGhngIdtthZzcc_Qi37lJ1MgATzBg,908
4
4
  toolsos/download.py,sha256=88hehmPL5m5d1nrcJjltuh4xrCItF5EYHaZdHOcSt-g,2652
5
- toolsos/geo.py,sha256=w0Bt0JJEILEjKtmKw97rHkVixkgbATS-uAQUV6WCHfQ,2598
6
- toolsos/helpers.py,sha256=VeOl-fLgePCbjEmAQdVmYe7z8OE1pISeDDuP1t5QSxM,997
5
+ toolsos/geo.py,sha256=YM877U6s7PVKi1kySQrENDbJxR1_bOnK3tyid0uszj0,3484
6
+ toolsos/helpers.py,sha256=U4MNRj8pz2iKOTMOzuRg-PdgIBBb21sedWYDWfstvWU,1319
7
7
  toolsos/polars_helpers.py,sha256=P3RHLQFeDL7-9U_Q1n4ma_NSkdYAiker4pnc57uluHw,770
8
8
  toolsos/database/database_connection.py,sha256=HCP8H_-iE2BOOQDp9v1HOgfUSX45XS-aqw7Nzf8drAU,4359
9
9
  toolsos/database/database_transfer.py,sha256=1ghq5VEtKyOdCKdM45uOyrZSoXMuWsdC35R3WNuFvdU,1827
@@ -16,11 +16,12 @@ toolsos/huisstijl/graphs/linegraph.py,sha256=dMUarRe31SXaY78OCXLy-PgnU8LlVJ9KkzK
16
16
  toolsos/huisstijl/graphs/piegraph.py,sha256=aEFiEM-9QuhBOjKHSXVuE5bTh-8uucq4FP6O8Vk1vZI,703
17
17
  toolsos/huisstijl/graphs/styler.py,sha256=-uZ7pjY1G39XvmaGHQd31gPRxjxmJGhYZk8xhy2JUWc,6623
18
18
  toolsos/huisstijl/maps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ toolsos/huisstijl/maps/choropleth.py,sha256=HbcXeeSNryGDT6vzCC7v1r6cYb-rQ7q5HqqpQo4PaUE,1899
19
20
  toolsos/huisstijl/tables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
21
  toolsos/huisstijl/tables/table_helpers.py,sha256=jsQ6lw93sxtGJGrUn8X2_LyA2vYYnytngpUI5A_wpWQ,2037
21
22
  toolsos/huisstijl/tables/table_styles.py,sha256=oYU6GJcfqlKpZof5PUjPsA7woJ3Tew78CHPyT0_jY6w,1343
22
- toolsos/huisstijl/tables/tables.py,sha256=w_8_KJhKDOxaLHouOYRG0pupgEqxy0qtty1DWD3rYc0,24488
23
- toolsos-0.2.7.dist-info/METADATA,sha256=CzVk1Oi9ZEDuXdIEVssMaX8sAL-d77ij8qz2o1BwmgM,2683
24
- toolsos-0.2.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
25
- toolsos-0.2.7.dist-info/top_level.txt,sha256=2ClEjUBbtfDQ8oPwvWRy1Sz2nrkLCXlg0mHaMdCWia0,8
26
- toolsos-0.2.7.dist-info/RECORD,,
23
+ toolsos/huisstijl/tables/tables.py,sha256=yeHiZd4EuOoeb_CeRE74xM1r1j6gCMNM1-I3Lpd2tyQ,24728
24
+ toolsos-0.3.0.dist-info/METADATA,sha256=zhUnPEX1TH0w6IWFuPCBZdDLSur9OsFUSt1nh1--tRA,2725
25
+ toolsos-0.3.0.dist-info/WHEEL,sha256=nn6H5-ilmfVryoAQl3ZQ2l8SH5imPWFpm1A5FgEuFV4,91
26
+ toolsos-0.3.0.dist-info/top_level.txt,sha256=2ClEjUBbtfDQ8oPwvWRy1Sz2nrkLCXlg0mHaMdCWia0,8
27
+ toolsos-0.3.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (75.8.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5