huff 1.3.0__tar.gz → 1.3.2__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.
- {huff-1.3.0/huff.egg-info → huff-1.3.2}/PKG-INFO +26 -4
- huff-1.3.0/PKG-INFO → huff-1.3.2/README.md +9 -11
- {huff-1.3.0 → huff-1.3.2}/huff/gistools.py +2 -2
- {huff-1.3.0 → huff-1.3.2}/huff/models.py +71 -26
- {huff-1.3.0 → huff-1.3.2}/huff/ors.py +9 -4
- {huff-1.3.0 → huff-1.3.2}/huff/osm.py +46 -3
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach.qmd +43 -43
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach_supermarkets.qmd +43 -43
- {huff-1.3.0 → huff-1.3.2}/huff/tests/tests_huff.py +74 -8
- huff-1.3.0/README.md → huff-1.3.2/huff.egg-info/PKG-INFO +33 -3
- {huff-1.3.0 → huff-1.3.2}/setup.py +1 -1
- {huff-1.3.0 → huff-1.3.2}/MANIFEST.in +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/__init__.py +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/__init__.py +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach.cpg +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach.dbf +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach.prj +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach.shp +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach.shx +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach_supermarkets.cpg +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach_supermarkets.dbf +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach_supermarkets.prj +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach_supermarkets.shp +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Haslach_supermarkets.shx +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff/tests/data/Wieland2015.xlsx +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff.egg-info/SOURCES.txt +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff.egg-info/dependency_links.txt +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff.egg-info/requires.txt +0 -0
- {huff-1.3.0 → huff-1.3.2}/huff.egg-info/top_level.txt +0 -0
- {huff-1.3.0 → huff-1.3.2}/setup.cfg +0 -0
@@ -1,13 +1,32 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: huff
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.2
|
4
4
|
Summary: huff: Huff Model Market Area Analysis
|
5
5
|
Author: Thomas Wieland
|
6
6
|
Author-email: geowieland@googlemail.com
|
7
7
|
Description-Content-Type: text/markdown
|
8
|
+
Requires-Dist: geopandas
|
9
|
+
Requires-Dist: pandas
|
10
|
+
Requires-Dist: numpy
|
11
|
+
Requires-Dist: statsmodels
|
12
|
+
Requires-Dist: shapely
|
13
|
+
Requires-Dist: requests
|
14
|
+
Requires-Dist: matplotlib
|
15
|
+
Requires-Dist: pillow
|
16
|
+
Requires-Dist: contextily
|
17
|
+
Requires-Dist: openpyxl
|
18
|
+
Dynamic: author
|
19
|
+
Dynamic: author-email
|
20
|
+
Dynamic: description
|
21
|
+
Dynamic: description-content-type
|
22
|
+
Dynamic: requires-dist
|
23
|
+
Dynamic: summary
|
8
24
|
|
9
25
|
# huff: Huff Model Market Area Analysis
|
10
26
|
|
27
|
+
This Python library is designed for performing market area analyses with the Huff Model (Huff 1962, 1964) and/or the Multiplicative Competitive Interaction (MCI) Model (Nakanishi and Cooper 1974, 1982). Users may load point shapefiles (or CSV, XLSX) of customer origins and supply locations and conduct a market area analysis step by step. The package also includes supplementary GIS functions, including clients for OpenRouteService(1) for network analysis (e.g., transport cost matrix) and OpenStreetMap(2) for simple maps. See Huff and McCallum (2008) or Wieland (2017) for a description of the models and their practical application.
|
28
|
+
|
29
|
+
|
11
30
|
## Author
|
12
31
|
|
13
32
|
Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geowieland@googlemail.com)
|
@@ -26,23 +45,26 @@ See the /tests directory for usage examples of most of the included functions.
|
|
26
45
|
- Fitting MCI model with >= 2 independent variables
|
27
46
|
- MCI model market simulation
|
28
47
|
- **GIS tools**:
|
29
|
-
- OpenRouteService
|
48
|
+
- OpenRouteService(1) Client:
|
30
49
|
- Creating transport costs matrix from origins and destinations
|
31
50
|
- Creating isochrones from origins and destinations
|
32
|
-
- OpenStreetMap
|
51
|
+
- OpenStreetMap(2) Client:
|
33
52
|
- Creating simple maps with OSM basemap
|
34
53
|
- Other GIS tools:
|
35
54
|
- Creating buffers from geodata
|
36
55
|
- Spatial join with with statistics
|
37
56
|
- Creating euclidean distance matrix from origins and destinations
|
38
57
|
- Overlay-difference analysis of polygons
|
58
|
+
- Hansen accessibility
|
39
59
|
- **Data management tools**:
|
40
60
|
- Loading own interaction matrix for analysis
|
41
61
|
- Creating origins/destinations objects from point geodata
|
42
62
|
|
43
63
|
(1) © openrouteservice.org by HeiGIT | Map data © OpenStreetMap contributors | https://openrouteservice.org/
|
64
|
+
|
44
65
|
(2) © OpenStreetMap contributors | available under the Open Database License | https://www.openstreetmap.org/
|
45
66
|
|
67
|
+
|
46
68
|
## Literature
|
47
69
|
- Huff DL (1962) *Determination of Intra-Urban Retail Trade Areas*.
|
48
70
|
- Huff DL (1964) Defining and estimating a trading area. *Journal of Marketing* 28(4): 34–38. [10.2307/1249154](https://doi.org/10.2307/1249154)
|
@@ -1,13 +1,8 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: huff
|
3
|
-
Version: 1.3.0
|
4
|
-
Summary: huff: Huff Model Market Area Analysis
|
5
|
-
Author: Thomas Wieland
|
6
|
-
Author-email: geowieland@googlemail.com
|
7
|
-
Description-Content-Type: text/markdown
|
8
|
-
|
9
1
|
# huff: Huff Model Market Area Analysis
|
10
2
|
|
3
|
+
This Python library is designed for performing market area analyses with the Huff Model (Huff 1962, 1964) and/or the Multiplicative Competitive Interaction (MCI) Model (Nakanishi and Cooper 1974, 1982). Users may load point shapefiles (or CSV, XLSX) of customer origins and supply locations and conduct a market area analysis step by step. The package also includes supplementary GIS functions, including clients for OpenRouteService(1) for network analysis (e.g., transport cost matrix) and OpenStreetMap(2) for simple maps. See Huff and McCallum (2008) or Wieland (2017) for a description of the models and their practical application.
|
4
|
+
|
5
|
+
|
11
6
|
## Author
|
12
7
|
|
13
8
|
Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geowieland@googlemail.com)
|
@@ -26,23 +21,26 @@ See the /tests directory for usage examples of most of the included functions.
|
|
26
21
|
- Fitting MCI model with >= 2 independent variables
|
27
22
|
- MCI model market simulation
|
28
23
|
- **GIS tools**:
|
29
|
-
- OpenRouteService
|
24
|
+
- OpenRouteService(1) Client:
|
30
25
|
- Creating transport costs matrix from origins and destinations
|
31
26
|
- Creating isochrones from origins and destinations
|
32
|
-
- OpenStreetMap
|
27
|
+
- OpenStreetMap(2) Client:
|
33
28
|
- Creating simple maps with OSM basemap
|
34
29
|
- Other GIS tools:
|
35
30
|
- Creating buffers from geodata
|
36
31
|
- Spatial join with with statistics
|
37
32
|
- Creating euclidean distance matrix from origins and destinations
|
38
33
|
- Overlay-difference analysis of polygons
|
34
|
+
- Hansen accessibility
|
39
35
|
- **Data management tools**:
|
40
36
|
- Loading own interaction matrix for analysis
|
41
37
|
- Creating origins/destinations objects from point geodata
|
42
38
|
|
43
39
|
(1) © openrouteservice.org by HeiGIT | Map data © OpenStreetMap contributors | https://openrouteservice.org/
|
40
|
+
|
44
41
|
(2) © OpenStreetMap contributors | available under the Open Database License | https://www.openstreetmap.org/
|
45
42
|
|
43
|
+
|
46
44
|
## Literature
|
47
45
|
- Huff DL (1962) *Determination of Intra-Urban Retail Trade Areas*.
|
48
46
|
- Huff DL (1964) Defining and estimating a trading area. *Journal of Marketing* 28(4): 34–38. [10.2307/1249154](https://doi.org/10.2307/1249154)
|
@@ -60,4 +58,4 @@ See the /tests directory for usage examples of most of the included functions.
|
|
60
58
|
To install the package, use `pip`:
|
61
59
|
|
62
60
|
```bash
|
63
|
-
pip install huff
|
61
|
+
pip install huff
|
@@ -4,8 +4,8 @@
|
|
4
4
|
# Author: Thomas Wieland
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
6
6
|
# mail: geowieland@googlemail.com
|
7
|
-
# Version: 1.3.
|
8
|
-
# Last update: 2025-05-
|
7
|
+
# Version: 1.3.2
|
8
|
+
# Last update: 2025-05-30 11:06
|
9
9
|
# Copyright (c) 2025 Thomas Wieland
|
10
10
|
#-----------------------------------------------------------------------
|
11
11
|
|
@@ -4,8 +4,8 @@
|
|
4
4
|
# Author: Thomas Wieland
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
6
6
|
# mail: geowieland@googlemail.com
|
7
|
-
# Version: 1.3.
|
8
|
-
# Last update: 2025-05-
|
7
|
+
# Version: 1.3.2
|
8
|
+
# Last update: 2025-05-30 11:06
|
9
9
|
# Copyright (c) 2025 Thomas Wieland
|
10
10
|
#-----------------------------------------------------------------------
|
11
11
|
|
@@ -50,11 +50,11 @@ class CustomerOrigins:
|
|
50
50
|
|
51
51
|
return self.metadata
|
52
52
|
|
53
|
-
def
|
53
|
+
def get_isochrones_gdf(self):
|
54
54
|
|
55
55
|
return self.isochrones_gdf
|
56
56
|
|
57
|
-
def
|
57
|
+
def get_buffers_gdf(self):
|
58
58
|
|
59
59
|
return self.buffers_gdf
|
60
60
|
|
@@ -62,7 +62,7 @@ class CustomerOrigins:
|
|
62
62
|
|
63
63
|
metadata = self.metadata
|
64
64
|
|
65
|
-
print("
|
65
|
+
print("Customer Origins")
|
66
66
|
print("No. locations " + str(metadata["no_points"]))
|
67
67
|
|
68
68
|
if metadata["marketsize_col"] is None:
|
@@ -230,11 +230,8 @@ class SupplyLocations:
|
|
230
230
|
|
231
231
|
metadata = self.metadata
|
232
232
|
|
233
|
-
print("
|
233
|
+
print("Supply Locations")
|
234
234
|
print("No. locations " + str(metadata["no_points"]))
|
235
|
-
|
236
|
-
if metadata["attraction_col"][0] is None or metadata["attraction_col"] == []:
|
237
|
-
print("Attraction column(s) not defined")
|
238
235
|
else:
|
239
236
|
print("Attraction column(s) " + ",".join(metadata["attraction_col"]))
|
240
237
|
|
@@ -443,7 +440,7 @@ class InteractionMatrix:
|
|
443
440
|
customer_origins_metadata = self.get_customer_origins().get_metadata()
|
444
441
|
supply_locations_metadata = self.get_supply_locations().get_metadata()
|
445
442
|
|
446
|
-
print("
|
443
|
+
print("Interaction Matrix")
|
447
444
|
print("----------------------------------")
|
448
445
|
print("Supply locations " + str(supply_locations_metadata["no_points"]))
|
449
446
|
if supply_locations_metadata["attraction_col"][0] is None:
|
@@ -659,7 +656,7 @@ class InteractionMatrix:
|
|
659
656
|
|
660
657
|
return self
|
661
658
|
|
662
|
-
def marketareas
|
659
|
+
def marketareas(self):
|
663
660
|
|
664
661
|
interaction_matrix_df = self.interaction_matrix_df
|
665
662
|
|
@@ -679,6 +676,29 @@ class InteractionMatrix:
|
|
679
676
|
|
680
677
|
return huff_model
|
681
678
|
|
679
|
+
|
680
|
+
def hansen(
|
681
|
+
self,
|
682
|
+
from_origins: bool = True
|
683
|
+
):
|
684
|
+
|
685
|
+
interaction_matrix_df = self.interaction_matrix_df
|
686
|
+
|
687
|
+
if interaction_matrix_df["U_ij"].isna().all():
|
688
|
+
self.utility()
|
689
|
+
interaction_matrix_df = self.interaction_matrix_df
|
690
|
+
|
691
|
+
if from_origins:
|
692
|
+
hansen_df = pd.DataFrame(interaction_matrix_df.groupby("i")["U_ij"].sum()).reset_index()
|
693
|
+
hansen_df = hansen_df.rename(columns = {"U_ij": "A_i"})
|
694
|
+
else:
|
695
|
+
hansen_df = pd.DataFrame(interaction_matrix_df.groupby("j")["U_ij"].sum()).reset_index()
|
696
|
+
hansen_df = hansen_df.rename(columns = {"U_ij": "A_j"})
|
697
|
+
|
698
|
+
return hansen_df
|
699
|
+
|
700
|
+
=======
|
701
|
+
>>>>>>> e9583d0cd7f349f17f005df0fa75e70160655aa3
|
682
702
|
def mci_transformation(
|
683
703
|
self,
|
684
704
|
cols: list = ["A_j", "t_ij"]
|
@@ -1017,8 +1037,7 @@ class MCIModel:
|
|
1017
1037
|
transformation = "LCT"
|
1018
1038
|
):
|
1019
1039
|
|
1020
|
-
interaction_matrix = self.interaction_matrix
|
1021
|
-
|
1040
|
+
interaction_matrix = self.interaction_matrix
|
1022
1041
|
interaction_matrix_df = interaction_matrix.get_interaction_matrix_df()
|
1023
1042
|
|
1024
1043
|
if interaction_matrix_df["t_ij"].isna().all():
|
@@ -1031,7 +1050,8 @@ class MCIModel:
|
|
1031
1050
|
cols = ["A_j", "t_ij"]
|
1032
1051
|
)
|
1033
1052
|
|
1034
|
-
|
1053
|
+
customer_origins = interaction_matrix.get_customer_origins()
|
1054
|
+
customer_origins_metadata = customer_origins.get_metadata()
|
1035
1055
|
|
1036
1056
|
t_ij_weighting = customer_origins_metadata["weighting"][0]["param"]
|
1037
1057
|
|
@@ -1040,7 +1060,8 @@ class MCIModel:
|
|
1040
1060
|
else:
|
1041
1061
|
mci_formula = f"t_ij**{t_ij_weighting}"
|
1042
1062
|
|
1043
|
-
|
1063
|
+
supply_locations = interaction_matrix.get_supply_locations()
|
1064
|
+
supply_locations_metadata = supply_locations.get_metadata()
|
1044
1065
|
attraction_col = supply_locations_metadata["attraction_col"]
|
1045
1066
|
attraction_weighting = supply_locations_metadata["weighting"]
|
1046
1067
|
|
@@ -1056,17 +1077,27 @@ class MCIModel:
|
|
1056
1077
|
if transformation == "ILCT":
|
1057
1078
|
interaction_matrix_df["U_ij"] = np.exp(interaction_matrix_df["U_ij"])
|
1058
1079
|
|
1059
|
-
|
1080
|
+
interaction_matrix = InteractionMatrix(
|
1081
|
+
interaction_matrix_df,
|
1082
|
+
customer_origins,
|
1083
|
+
supply_locations
|
1084
|
+
)
|
1085
|
+
self.interaction_matrix = interaction_matrix
|
1060
1086
|
|
1061
1087
|
return self
|
1062
1088
|
|
1063
|
-
def probabilities (
|
1089
|
+
def probabilities (
|
1090
|
+
self,
|
1091
|
+
transformation = "LCT"
|
1092
|
+
):
|
1064
1093
|
|
1065
|
-
|
1094
|
+
interaction_matrix = self.interaction_matrix
|
1095
|
+
interaction_matrix_df = interaction_matrix.get_interaction_matrix_df()
|
1066
1096
|
|
1067
1097
|
if interaction_matrix_df["U_ij"].isna().all():
|
1068
|
-
self.utility()
|
1069
|
-
|
1098
|
+
self.utility(transformation = transformation)
|
1099
|
+
interaction_matrix = self.interaction_matrix
|
1100
|
+
interaction_matrix_df = interaction_matrix.get_interaction_matrix_df()
|
1070
1101
|
|
1071
1102
|
utility_i = pd.DataFrame(interaction_matrix_df.groupby("i")["U_ij"].sum())
|
1072
1103
|
utility_i = utility_i.rename(columns = {"U_ij": "U_i"})
|
@@ -1082,14 +1113,22 @@ class MCIModel:
|
|
1082
1113
|
|
1083
1114
|
interaction_matrix_df = interaction_matrix_df.drop(columns=["U_i"])
|
1084
1115
|
|
1085
|
-
|
1116
|
+
interaction_matrix.interaction_matrix_df = interaction_matrix_df
|
1117
|
+
self.interaction_matrix = interaction_matrix
|
1086
1118
|
|
1087
1119
|
return self
|
1088
1120
|
|
1089
|
-
def flows (
|
1121
|
+
def flows (
|
1122
|
+
self,
|
1123
|
+
transformation = "LCT"
|
1124
|
+
):
|
1090
1125
|
|
1091
|
-
|
1126
|
+
interaction_matrix = self.interaction_matrix
|
1127
|
+
interaction_matrix_df = interaction_matrix.get_interaction_matrix_df()
|
1092
1128
|
|
1129
|
+
if "C_i" not in interaction_matrix_df.columns:
|
1130
|
+
raise ValueError ("No market size column defined in interaction matrix.")
|
1131
|
+
|
1093
1132
|
if interaction_matrix_df["C_i"].isna().all():
|
1094
1133
|
raise ValueError ("Market size column in customer origins not defined. Use CustomerOrigins.define_marketsize()")
|
1095
1134
|
|
@@ -1099,8 +1138,9 @@ class MCIModel:
|
|
1099
1138
|
)
|
1100
1139
|
|
1101
1140
|
if interaction_matrix_df["p_ij"].isna().all():
|
1102
|
-
self.probabilities()
|
1103
|
-
|
1141
|
+
self.probabilities(transformation=transformation)
|
1142
|
+
interaction_matrix = self.interaction_matrix
|
1143
|
+
interaction_matrix_df = interaction_matrix.get_interaction_matrix_df()
|
1104
1144
|
|
1105
1145
|
interaction_matrix_df["E_ij"] = interaction_matrix_df["p_ij"] * interaction_matrix_df["C_i"]
|
1106
1146
|
|
@@ -1573,7 +1613,7 @@ def get_isochrones(
|
|
1573
1613
|
profile: str = "driving-car",
|
1574
1614
|
donut: bool = True,
|
1575
1615
|
ors_server: str = "https://api.openrouteservice.org/v2/",
|
1576
|
-
ors_auth: str = None,
|
1616
|
+
ors_auth: str = None,
|
1577
1617
|
timeout = 10,
|
1578
1618
|
delay = 1,
|
1579
1619
|
save_output: bool = True,
|
@@ -1623,6 +1663,8 @@ def get_isochrones(
|
|
1623
1663
|
time.sleep(delay)
|
1624
1664
|
|
1625
1665
|
isochrone_gdf[unique_id_col] = unique_id_values[i]
|
1666
|
+
|
1667
|
+
isochrone_gdf["segment_minutes"] = isochrone_gdf["segment"]/60
|
1626
1668
|
|
1627
1669
|
isochrones_gdf = pd.concat(
|
1628
1670
|
[
|
@@ -1634,6 +1676,9 @@ def get_isochrones(
|
|
1634
1676
|
|
1635
1677
|
i = i+1
|
1636
1678
|
|
1679
|
+
isochrones_gdf["segment"] = isochrones_gdf["segment"].astype(int)
|
1680
|
+
isochrones_gdf["segment_minutes"] = isochrones_gdf["segment_minutes"].astype(int)
|
1681
|
+
|
1637
1682
|
isochrones_gdf.set_crs(
|
1638
1683
|
output_crs,
|
1639
1684
|
allow_override=True,
|
@@ -4,8 +4,8 @@
|
|
4
4
|
# Author: Thomas Wieland
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
6
6
|
# mail: geowieland@googlemail.com
|
7
|
-
# Version: 1.2
|
8
|
-
# Last update: 2025-05-
|
7
|
+
# Version: 1.3.2
|
8
|
+
# Last update: 2025-05-30 11:07
|
9
9
|
# Copyright (c) 2025 Thomas Wieland
|
10
10
|
#-----------------------------------------------------------------------
|
11
11
|
|
@@ -119,7 +119,6 @@ class Client:
|
|
119
119
|
def isochrone(
|
120
120
|
self,
|
121
121
|
locations: list,
|
122
|
-
id: list = [],
|
123
122
|
segments: list = [900, 600, 300],
|
124
123
|
range_type: str = "time",
|
125
124
|
intersections: str = "true",
|
@@ -130,6 +129,12 @@ class Client:
|
|
130
129
|
output_crs: str = "EPSG:4326"
|
131
130
|
):
|
132
131
|
|
132
|
+
if len(segments) > 10:
|
133
|
+
raise ValueError ("ORS client does not allow >10 intervals in an Isochrones query. See https://openrouteservice.org/restrictions/.")
|
134
|
+
|
135
|
+
if len(locations) > 5:
|
136
|
+
raise ValueError ("ORS client does not allow >5 locations in an Isochrones query. See https://openrouteservice.org/restrictions/.")
|
137
|
+
|
133
138
|
ors_url = self.server + "isochrones/" + profile
|
134
139
|
auth = self.auth
|
135
140
|
|
@@ -200,7 +205,7 @@ class Client:
|
|
200
205
|
|
201
206
|
isochrones_gdf["segment"] = 0
|
202
207
|
isochrones_gdf_properties_dict = dict(isochrones_gdf["properties"])
|
203
|
-
|
208
|
+
|
204
209
|
for i in range(len(isochrones_gdf_properties_dict)):
|
205
210
|
isochrones_gdf.iloc[i,3] = isochrones_gdf_properties_dict[i]["value"]
|
206
211
|
|
@@ -4,8 +4,8 @@
|
|
4
4
|
# Author: Thomas Wieland
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
6
6
|
# mail: geowieland@googlemail.com
|
7
|
-
# Version: 1.
|
8
|
-
# Last update: 2025-05-
|
7
|
+
# Version: 1.3.2
|
8
|
+
# Last update: 2025-05-30 11:07
|
9
9
|
# Copyright (c) 2025 Thomas Wieland
|
10
10
|
#-----------------------------------------------------------------------
|
11
11
|
|
@@ -173,9 +173,52 @@ def map_with_basemap(
|
|
173
173
|
extent_img = [sw_lon, ne_lon, sw_lat, ne_lat]
|
174
174
|
ax.imshow(img, extent=extent_img, origin="upper")
|
175
175
|
|
176
|
+
i = 0
|
176
177
|
for layer in layers:
|
178
|
+
|
177
179
|
layer_3857 = layer.to_crs(epsg=3857)
|
178
|
-
|
180
|
+
|
181
|
+
if styles != {}:
|
182
|
+
|
183
|
+
layer_style = styles[i]
|
184
|
+
layer_color = layer_style["color"]
|
185
|
+
layer_alpha = layer_style["alpha"]
|
186
|
+
|
187
|
+
if isinstance(layer_color, str):
|
188
|
+
|
189
|
+
layer_3857.plot(
|
190
|
+
ax=ax,
|
191
|
+
color=layer_color,
|
192
|
+
alpha=layer_alpha
|
193
|
+
)
|
194
|
+
|
195
|
+
elif isinstance(layer_color, dict):
|
196
|
+
|
197
|
+
color_key = list(layer_color.keys())[0]
|
198
|
+
color_mapping = layer_color[color_key]
|
199
|
+
|
200
|
+
if color_key not in layer_3857.columns:
|
201
|
+
raise KeyError ("Column", color_key, "not in layer.")
|
202
|
+
|
203
|
+
for value, color in color_mapping.items():
|
204
|
+
|
205
|
+
subset = layer_3857[layer_3857[color_key].astype(str) == str(value)]
|
206
|
+
|
207
|
+
if not subset.empty:
|
208
|
+
subset.plot(
|
209
|
+
ax=ax,
|
210
|
+
color=color,
|
211
|
+
alpha=layer_alpha
|
212
|
+
)
|
213
|
+
|
214
|
+
else:
|
215
|
+
|
216
|
+
layer_3857.plot(
|
217
|
+
ax=ax,
|
218
|
+
alpha=0.6
|
219
|
+
)
|
220
|
+
|
221
|
+
i = i+1
|
179
222
|
|
180
223
|
bbox = box(sw_lon, sw_lat, ne_lon, ne_lat)
|
181
224
|
extent_geom = gpd.GeoSeries([bbox], crs=4326).to_crs(epsg=3857).total_bounds
|
@@ -1,43 +1,43 @@
|
|
1
|
-
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
2
|
-
<qgis version="3.28.3-Firenze">
|
3
|
-
<identifier></identifier>
|
4
|
-
<parentidentifier></parentidentifier>
|
5
|
-
<language></language>
|
6
|
-
<type>dataset</type>
|
7
|
-
<title></title>
|
8
|
-
<abstract></abstract>
|
9
|
-
<contact>
|
10
|
-
<name></name>
|
11
|
-
<organization></organization>
|
12
|
-
<position></position>
|
13
|
-
<voice></voice>
|
14
|
-
<fax></fax>
|
15
|
-
<email></email>
|
16
|
-
<role></role>
|
17
|
-
</contact>
|
18
|
-
<links/>
|
19
|
-
<fees></fees>
|
20
|
-
<encoding></encoding>
|
21
|
-
<crs>
|
22
|
-
<spatialrefsys nativeFormat="Wkt">
|
23
|
-
<wkt>PROJCRS["DHDN / 3-degree Gauss-Kruger zone 3",BASEGEOGCRS["DHDN",DATUM["Deutsches Hauptdreiecksnetz",ELLIPSOID["Bessel 1841",6377397.155,299.1528128,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4314]],CONVERSION["3-degree Gauss-Kruger zone 3",METHOD["Transverse Mercator",ID["EPSG",9807]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",9,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["Scale factor at natural origin",1,SCALEUNIT["unity",1],ID["EPSG",8805]],PARAMETER["False easting",3500000,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["northing (X)",north,ORDER[1],LENGTHUNIT["metre",1]],AXIS["easting (Y)",east,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Cadastre, engineering survey, topographic mapping."],AREA["Germany - former West Germany onshore between 7�30'E and 10�30'E - states of Baden-Wurtemberg, Bayern, Bremen, Hamberg, Hessen, Niedersachsen, Nordrhein-Westfalen, Rhineland-Pfalz, Schleswig-Holstein."],BBOX[47.27,7.5,55.09,10.51]],ID["EPSG",31467]]</wkt>
|
24
|
-
<proj4>+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +ellps=bessel +towgs84=598.1,73.7,418.2,0.202,0.045,-2.455,6.7 +units=m +no_defs</proj4>
|
25
|
-
<srsid>2647</srsid>
|
26
|
-
<srid>31467</srid>
|
27
|
-
<authid>EPSG:31467</authid>
|
28
|
-
<description>DHDN / 3-degree Gauss-Kruger zone 3</description>
|
29
|
-
<projectionacronym>tmerc</projectionacronym>
|
30
|
-
<ellipsoidacronym>EPSG:7004</ellipsoidacronym>
|
31
|
-
<geographicflag>false</geographicflag>
|
32
|
-
</spatialrefsys>
|
33
|
-
</crs>
|
34
|
-
<extent>
|
35
|
-
<spatial maxy="0" dimensions="2" maxx="0" maxz="0" crs="EPSG:31467" miny="0" minz="0" minx="0"/>
|
36
|
-
<temporal>
|
37
|
-
<period>
|
38
|
-
<start></start>
|
39
|
-
<end></end>
|
40
|
-
</period>
|
41
|
-
</temporal>
|
42
|
-
</extent>
|
43
|
-
</qgis>
|
1
|
+
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
2
|
+
<qgis version="3.28.3-Firenze">
|
3
|
+
<identifier></identifier>
|
4
|
+
<parentidentifier></parentidentifier>
|
5
|
+
<language></language>
|
6
|
+
<type>dataset</type>
|
7
|
+
<title></title>
|
8
|
+
<abstract></abstract>
|
9
|
+
<contact>
|
10
|
+
<name></name>
|
11
|
+
<organization></organization>
|
12
|
+
<position></position>
|
13
|
+
<voice></voice>
|
14
|
+
<fax></fax>
|
15
|
+
<email></email>
|
16
|
+
<role></role>
|
17
|
+
</contact>
|
18
|
+
<links/>
|
19
|
+
<fees></fees>
|
20
|
+
<encoding></encoding>
|
21
|
+
<crs>
|
22
|
+
<spatialrefsys nativeFormat="Wkt">
|
23
|
+
<wkt>PROJCRS["DHDN / 3-degree Gauss-Kruger zone 3",BASEGEOGCRS["DHDN",DATUM["Deutsches Hauptdreiecksnetz",ELLIPSOID["Bessel 1841",6377397.155,299.1528128,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4314]],CONVERSION["3-degree Gauss-Kruger zone 3",METHOD["Transverse Mercator",ID["EPSG",9807]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",9,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["Scale factor at natural origin",1,SCALEUNIT["unity",1],ID["EPSG",8805]],PARAMETER["False easting",3500000,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["northing (X)",north,ORDER[1],LENGTHUNIT["metre",1]],AXIS["easting (Y)",east,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Cadastre, engineering survey, topographic mapping."],AREA["Germany - former West Germany onshore between 7�30'E and 10�30'E - states of Baden-Wurtemberg, Bayern, Bremen, Hamberg, Hessen, Niedersachsen, Nordrhein-Westfalen, Rhineland-Pfalz, Schleswig-Holstein."],BBOX[47.27,7.5,55.09,10.51]],ID["EPSG",31467]]</wkt>
|
24
|
+
<proj4>+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +ellps=bessel +towgs84=598.1,73.7,418.2,0.202,0.045,-2.455,6.7 +units=m +no_defs</proj4>
|
25
|
+
<srsid>2647</srsid>
|
26
|
+
<srid>31467</srid>
|
27
|
+
<authid>EPSG:31467</authid>
|
28
|
+
<description>DHDN / 3-degree Gauss-Kruger zone 3</description>
|
29
|
+
<projectionacronym>tmerc</projectionacronym>
|
30
|
+
<ellipsoidacronym>EPSG:7004</ellipsoidacronym>
|
31
|
+
<geographicflag>false</geographicflag>
|
32
|
+
</spatialrefsys>
|
33
|
+
</crs>
|
34
|
+
<extent>
|
35
|
+
<spatial maxy="0" dimensions="2" maxx="0" maxz="0" crs="EPSG:31467" miny="0" minz="0" minx="0"/>
|
36
|
+
<temporal>
|
37
|
+
<period>
|
38
|
+
<start></start>
|
39
|
+
<end></end>
|
40
|
+
</period>
|
41
|
+
</temporal>
|
42
|
+
</extent>
|
43
|
+
</qgis>
|
@@ -1,43 +1,43 @@
|
|
1
|
-
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
2
|
-
<qgis version="3.28.3-Firenze">
|
3
|
-
<identifier></identifier>
|
4
|
-
<parentidentifier></parentidentifier>
|
5
|
-
<language></language>
|
6
|
-
<type>dataset</type>
|
7
|
-
<title></title>
|
8
|
-
<abstract></abstract>
|
9
|
-
<contact>
|
10
|
-
<name></name>
|
11
|
-
<organization></organization>
|
12
|
-
<position></position>
|
13
|
-
<voice></voice>
|
14
|
-
<fax></fax>
|
15
|
-
<email></email>
|
16
|
-
<role></role>
|
17
|
-
</contact>
|
18
|
-
<links/>
|
19
|
-
<fees></fees>
|
20
|
-
<encoding></encoding>
|
21
|
-
<crs>
|
22
|
-
<spatialrefsys nativeFormat="Wkt">
|
23
|
-
<wkt>PROJCRS["DHDN / 3-degree Gauss-Kruger zone 3",BASEGEOGCRS["DHDN",DATUM["Deutsches Hauptdreiecksnetz",ELLIPSOID["Bessel 1841",6377397.155,299.1528128,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4314]],CONVERSION["3-degree Gauss-Kruger zone 3",METHOD["Transverse Mercator",ID["EPSG",9807]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",9,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["Scale factor at natural origin",1,SCALEUNIT["unity",1],ID["EPSG",8805]],PARAMETER["False easting",3500000,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["northing (X)",north,ORDER[1],LENGTHUNIT["metre",1]],AXIS["easting (Y)",east,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Cadastre, engineering survey, topographic mapping."],AREA["Germany - former West Germany onshore between 7�30'E and 10�30'E - states of Baden-Wurtemberg, Bayern, Bremen, Hamberg, Hessen, Niedersachsen, Nordrhein-Westfalen, Rhineland-Pfalz, Schleswig-Holstein."],BBOX[47.27,7.5,55.09,10.51]],ID["EPSG",31467]]</wkt>
|
24
|
-
<proj4>+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +ellps=bessel +towgs84=598.1,73.7,418.2,0.202,0.045,-2.455,6.7 +units=m +no_defs</proj4>
|
25
|
-
<srsid>2647</srsid>
|
26
|
-
<srid>31467</srid>
|
27
|
-
<authid>EPSG:31467</authid>
|
28
|
-
<description>DHDN / 3-degree Gauss-Kruger zone 3</description>
|
29
|
-
<projectionacronym>tmerc</projectionacronym>
|
30
|
-
<ellipsoidacronym>EPSG:7004</ellipsoidacronym>
|
31
|
-
<geographicflag>false</geographicflag>
|
32
|
-
</spatialrefsys>
|
33
|
-
</crs>
|
34
|
-
<extent>
|
35
|
-
<spatial maxy="0" dimensions="2" maxx="0" maxz="0" crs="EPSG:31467" miny="0" minz="0" minx="0"/>
|
36
|
-
<temporal>
|
37
|
-
<period>
|
38
|
-
<start></start>
|
39
|
-
<end></end>
|
40
|
-
</period>
|
41
|
-
</temporal>
|
42
|
-
</extent>
|
43
|
-
</qgis>
|
1
|
+
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
2
|
+
<qgis version="3.28.3-Firenze">
|
3
|
+
<identifier></identifier>
|
4
|
+
<parentidentifier></parentidentifier>
|
5
|
+
<language></language>
|
6
|
+
<type>dataset</type>
|
7
|
+
<title></title>
|
8
|
+
<abstract></abstract>
|
9
|
+
<contact>
|
10
|
+
<name></name>
|
11
|
+
<organization></organization>
|
12
|
+
<position></position>
|
13
|
+
<voice></voice>
|
14
|
+
<fax></fax>
|
15
|
+
<email></email>
|
16
|
+
<role></role>
|
17
|
+
</contact>
|
18
|
+
<links/>
|
19
|
+
<fees></fees>
|
20
|
+
<encoding></encoding>
|
21
|
+
<crs>
|
22
|
+
<spatialrefsys nativeFormat="Wkt">
|
23
|
+
<wkt>PROJCRS["DHDN / 3-degree Gauss-Kruger zone 3",BASEGEOGCRS["DHDN",DATUM["Deutsches Hauptdreiecksnetz",ELLIPSOID["Bessel 1841",6377397.155,299.1528128,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4314]],CONVERSION["3-degree Gauss-Kruger zone 3",METHOD["Transverse Mercator",ID["EPSG",9807]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",9,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["Scale factor at natural origin",1,SCALEUNIT["unity",1],ID["EPSG",8805]],PARAMETER["False easting",3500000,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["northing (X)",north,ORDER[1],LENGTHUNIT["metre",1]],AXIS["easting (Y)",east,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Cadastre, engineering survey, topographic mapping."],AREA["Germany - former West Germany onshore between 7�30'E and 10�30'E - states of Baden-Wurtemberg, Bayern, Bremen, Hamberg, Hessen, Niedersachsen, Nordrhein-Westfalen, Rhineland-Pfalz, Schleswig-Holstein."],BBOX[47.27,7.5,55.09,10.51]],ID["EPSG",31467]]</wkt>
|
24
|
+
<proj4>+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +ellps=bessel +towgs84=598.1,73.7,418.2,0.202,0.045,-2.455,6.7 +units=m +no_defs</proj4>
|
25
|
+
<srsid>2647</srsid>
|
26
|
+
<srid>31467</srid>
|
27
|
+
<authid>EPSG:31467</authid>
|
28
|
+
<description>DHDN / 3-degree Gauss-Kruger zone 3</description>
|
29
|
+
<projectionacronym>tmerc</projectionacronym>
|
30
|
+
<ellipsoidacronym>EPSG:7004</ellipsoidacronym>
|
31
|
+
<geographicflag>false</geographicflag>
|
32
|
+
</spatialrefsys>
|
33
|
+
</crs>
|
34
|
+
<extent>
|
35
|
+
<spatial maxy="0" dimensions="2" maxx="0" maxz="0" crs="EPSG:31467" miny="0" minz="0" minx="0"/>
|
36
|
+
<temporal>
|
37
|
+
<period>
|
38
|
+
<start></start>
|
39
|
+
<end></end>
|
40
|
+
</period>
|
41
|
+
</temporal>
|
42
|
+
</extent>
|
43
|
+
</qgis>
|
@@ -4,8 +4,8 @@
|
|
4
4
|
# Author: Thomas Wieland
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
6
6
|
# mail: geowieland@googlemail.com
|
7
|
-
# Version: 1.3.
|
8
|
-
# Last update: 2025-05-
|
7
|
+
# Version: 1.3.2
|
8
|
+
# Last update: 2025-05-30 09:37
|
9
9
|
# Copyright (c) 2025 Thomas Wieland
|
10
10
|
#-----------------------------------------------------------------------
|
11
11
|
|
@@ -68,7 +68,7 @@ Haslach_supermarkets.define_attraction_weighting(
|
|
68
68
|
# Define attraction weighting (gamma)
|
69
69
|
|
70
70
|
Haslach_supermarkets.isochrones(
|
71
|
-
segments_minutes=[
|
71
|
+
segments_minutes=[3, 6, 9, 12, 15],
|
72
72
|
profile = "foot-walking",
|
73
73
|
save_output=True,
|
74
74
|
ors_auth="5b3ce3597851110001cf62480a15aafdb5a64f4d91805929f8af6abd",
|
@@ -102,6 +102,19 @@ interaction_matrix = haslach_interactionmatrix.transport_costs(
|
|
102
102
|
# Obtaining transport costs (default: driving-car)
|
103
103
|
# ORS API documentation: https://openrouteservice.org/dev/#/api-docs/v2/
|
104
104
|
|
105
|
+
interaction_matrix.summary()
|
106
|
+
# Summary of interaction matrix
|
107
|
+
|
108
|
+
print(interaction_matrix.hansen())
|
109
|
+
# Hansen accessibility for interaction matrix
|
110
|
+
|
111
|
+
interaction_matrix = interaction_matrix.flows()
|
112
|
+
# Calculating spatial flows for interaction matrix
|
113
|
+
|
114
|
+
huff_model = interaction_matrix.marketareas()
|
115
|
+
# Calculating total market areas for interaction matrix
|
116
|
+
# Result of class HuffModel
|
117
|
+
|
105
118
|
interaction_matrix = interaction_matrix.flows()
|
106
119
|
# Calculating spatial flows
|
107
120
|
|
@@ -170,22 +183,44 @@ Wieland2015_fit.summary()
|
|
170
183
|
# Buffer analysis:
|
171
184
|
|
172
185
|
Haslach_supermarkets_gdf = Haslach_supermarkets.get_geodata_gpd_original()
|
173
|
-
Haslach_buffers = Haslach_buf.
|
186
|
+
Haslach_buffers = Haslach_buf.get_buffers_gdf()
|
174
187
|
# Extracting points and buffer polygons
|
175
188
|
|
176
|
-
|
189
|
+
Haslach_districts_buf = point_spatial_join(
|
177
190
|
polygon_gdf = Haslach_buffers,
|
178
191
|
point_gdf = Haslach_supermarkets_gdf,
|
179
192
|
polygon_ref_cols = ["BEZEICHN", "segment"],
|
180
193
|
point_stat_col = "VKF_qm"
|
181
194
|
)
|
182
195
|
# Spatial join with buffers and points
|
183
|
-
# Statistics for
|
196
|
+
# Statistics for supermarket selling space by buffers of statistical districts
|
197
|
+
# (How much selling space in 500, 1000, and 1500 metres?)
|
198
|
+
|
199
|
+
Haslach_districts_buf[0].to_file("Haslach_districts_buf.shp")
|
200
|
+
# Save joined points as shapefile
|
201
|
+
|
202
|
+
print(Haslach_districts_buf[1])
|
203
|
+
# Showing df with overlay statistics
|
204
|
+
|
205
|
+
|
206
|
+
# Isochrones analysis:
|
207
|
+
|
208
|
+
Haslach_districts = Haslach.get_geodata_gpd_original()
|
209
|
+
|
210
|
+
Haslach_supermarkets_iso = point_spatial_join(
|
211
|
+
polygon_gdf = Haslach_supermarkets_isochrones,
|
212
|
+
point_gdf = Haslach_districts,
|
213
|
+
polygon_ref_cols = ["LFDNR", "segment"],
|
214
|
+
point_stat_col = "pop"
|
215
|
+
)
|
216
|
+
# Spatial join with isochrones and points
|
217
|
+
# Statistics for population by isochrones of supermarkets
|
218
|
+
# (How much population in 5, 10, and 15 minutes?)
|
184
219
|
|
185
|
-
|
220
|
+
Haslach_supermarkets_iso[0].to_file("Haslach_supermarkets_iso.shp")
|
186
221
|
# Save joined points as shapefile
|
187
222
|
|
188
|
-
print(
|
223
|
+
print(Haslach_supermarkets_iso[1])
|
189
224
|
# Showing df with overlay statistics
|
190
225
|
|
191
226
|
|
@@ -202,6 +237,37 @@ map_with_basemap(
|
|
202
237
|
Haslach_gdf,
|
203
238
|
Haslach_supermarkets_gdf
|
204
239
|
],
|
240
|
+
styles={
|
241
|
+
0: {
|
242
|
+
"color": {
|
243
|
+
"segment_minutes": {
|
244
|
+
"3": "green",
|
245
|
+
"6": "yellow",
|
246
|
+
"9": "orange",
|
247
|
+
"12": "red",
|
248
|
+
"13": "darkred"
|
249
|
+
}
|
250
|
+
},
|
251
|
+
"alpha": 0.3
|
252
|
+
},
|
253
|
+
1: {
|
254
|
+
"color": "green",
|
255
|
+
"alpha": 1
|
256
|
+
},
|
257
|
+
2: {
|
258
|
+
"color": {
|
259
|
+
"Name": {
|
260
|
+
"Aldi S├╝d": "blue",
|
261
|
+
"Edeka": "yellow",
|
262
|
+
"Lidl": "red",
|
263
|
+
"Netto": "orange",
|
264
|
+
"Real": "black",
|
265
|
+
"Treff 3000": "fuchsia"
|
266
|
+
}
|
267
|
+
},
|
268
|
+
"alpha": 1
|
269
|
+
}
|
270
|
+
},
|
205
271
|
output_filepath = "Haslach_map.png"
|
206
272
|
)
|
207
273
|
# Map with three layers and OSM basemap
|
@@ -1,5 +1,32 @@
|
|
1
|
+
Metadata-Version: 2.2
|
2
|
+
Name: huff
|
3
|
+
Version: 1.3.2
|
4
|
+
Summary: huff: Huff Model Market Area Analysis
|
5
|
+
Author: Thomas Wieland
|
6
|
+
Author-email: geowieland@googlemail.com
|
7
|
+
Description-Content-Type: text/markdown
|
8
|
+
Requires-Dist: geopandas
|
9
|
+
Requires-Dist: pandas
|
10
|
+
Requires-Dist: numpy
|
11
|
+
Requires-Dist: statsmodels
|
12
|
+
Requires-Dist: shapely
|
13
|
+
Requires-Dist: requests
|
14
|
+
Requires-Dist: matplotlib
|
15
|
+
Requires-Dist: pillow
|
16
|
+
Requires-Dist: contextily
|
17
|
+
Requires-Dist: openpyxl
|
18
|
+
Dynamic: author
|
19
|
+
Dynamic: author-email
|
20
|
+
Dynamic: description
|
21
|
+
Dynamic: description-content-type
|
22
|
+
Dynamic: requires-dist
|
23
|
+
Dynamic: summary
|
24
|
+
|
1
25
|
# huff: Huff Model Market Area Analysis
|
2
26
|
|
27
|
+
This Python library is designed for performing market area analyses with the Huff Model (Huff 1962, 1964) and/or the Multiplicative Competitive Interaction (MCI) Model (Nakanishi and Cooper 1974, 1982). Users may load point shapefiles (or CSV, XLSX) of customer origins and supply locations and conduct a market area analysis step by step. The package also includes supplementary GIS functions, including clients for OpenRouteService(1) for network analysis (e.g., transport cost matrix) and OpenStreetMap(2) for simple maps. See Huff and McCallum (2008) or Wieland (2017) for a description of the models and their practical application.
|
28
|
+
|
29
|
+
|
3
30
|
## Author
|
4
31
|
|
5
32
|
Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geowieland@googlemail.com)
|
@@ -18,23 +45,26 @@ See the /tests directory for usage examples of most of the included functions.
|
|
18
45
|
- Fitting MCI model with >= 2 independent variables
|
19
46
|
- MCI model market simulation
|
20
47
|
- **GIS tools**:
|
21
|
-
- OpenRouteService
|
48
|
+
- OpenRouteService(1) Client:
|
22
49
|
- Creating transport costs matrix from origins and destinations
|
23
50
|
- Creating isochrones from origins and destinations
|
24
|
-
- OpenStreetMap
|
51
|
+
- OpenStreetMap(2) Client:
|
25
52
|
- Creating simple maps with OSM basemap
|
26
53
|
- Other GIS tools:
|
27
54
|
- Creating buffers from geodata
|
28
55
|
- Spatial join with with statistics
|
29
56
|
- Creating euclidean distance matrix from origins and destinations
|
30
57
|
- Overlay-difference analysis of polygons
|
58
|
+
- Hansen accessibility
|
31
59
|
- **Data management tools**:
|
32
60
|
- Loading own interaction matrix for analysis
|
33
61
|
- Creating origins/destinations objects from point geodata
|
34
62
|
|
35
63
|
(1) © openrouteservice.org by HeiGIT | Map data © OpenStreetMap contributors | https://openrouteservice.org/
|
64
|
+
|
36
65
|
(2) © OpenStreetMap contributors | available under the Open Database License | https://www.openstreetmap.org/
|
37
66
|
|
67
|
+
|
38
68
|
## Literature
|
39
69
|
- Huff DL (1962) *Determination of Intra-Urban Retail Trade Areas*.
|
40
70
|
- Huff DL (1964) Defining and estimating a trading area. *Journal of Marketing* 28(4): 34–38. [10.2307/1249154](https://doi.org/10.2307/1249154)
|
@@ -52,4 +82,4 @@ See the /tests directory for usage examples of most of the included functions.
|
|
52
82
|
To install the package, use `pip`:
|
53
83
|
|
54
84
|
```bash
|
55
|
-
pip install huff
|
85
|
+
pip install huff
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|