huff 1.4.1__py3-none-any.whl → 1.5.1__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.
Binary file
huff/tests/tests_huff.py CHANGED
@@ -4,18 +4,17 @@
4
4
  # Author: Thomas Wieland
5
5
  # ORCID: 0000-0001-5168-9846
6
6
  # mail: geowieland@googlemail.com
7
- # Version: 1.4.1
8
- # Last update: 2025-06-16 17:43
7
+ # Version: 1.5.1
8
+ # Last update: 2025-07-01 17:10
9
9
  # Copyright (c) 2025 Thomas Wieland
10
10
  #-----------------------------------------------------------------------
11
11
 
12
-
13
- from huff.models import create_interaction_matrix, get_isochrones, load_geodata, load_interaction_matrix, market_shares, modelfit
12
+ from huff.models import create_interaction_matrix, get_isochrones, load_geodata, load_interaction_matrix, load_marketareas, market_shares, modelfit
14
13
  from huff.osm import map_with_basemap
15
14
  from huff.gistools import buffers, point_spatial_join
16
15
 
17
16
 
18
- # Customer origins (statistical districts):
17
+ # Dealing with customer origins (statistical districts):
19
18
 
20
19
  Haslach = load_geodata(
21
20
  "data/Haslach.shp",
@@ -39,10 +38,8 @@ Haslach.define_marketsize("pop")
39
38
  # Definition of market size variable
40
39
 
41
40
  Haslach.define_transportcosts_weighting(
42
- # param_lambda = -2.2,
43
- # # one weighting parameter for power function (default)
44
- param_lambda = [10, -0.5],
45
- func="logistic"
41
+ param_lambda = -2.2,
42
+ # one weighting parameter for power function (default)
46
43
  # two weighting parameters for logistic function
47
44
  )
48
45
  # Definition of transport costs weighting (lambda)
@@ -51,7 +48,7 @@ Haslach.summary()
51
48
  # Summary after update
52
49
 
53
50
 
54
- # Supply locations (supermarkets):
51
+ # Dealing with upply locations (supermarkets):
55
52
 
56
53
  Haslach_supermarkets = load_geodata(
57
54
  "data/Haslach_supermarkets.shp",
@@ -87,9 +84,7 @@ Haslach_supermarkets.summary()
87
84
  # Summary of updated customer origins
88
85
 
89
86
  Haslach_supermarkets_isochrones = Haslach_supermarkets.get_isochrones_gdf()
90
- # Extracting isochrones
91
-
92
- print(Haslach_supermarkets_isochrones)
87
+ # Extracting isochrones as gdf
93
88
 
94
89
 
95
90
  # Using customer origins and supply locations for building interaction matrix:
@@ -101,8 +96,8 @@ haslach_interactionmatrix = create_interaction_matrix(
101
96
  # Creating interaction matrix
102
97
 
103
98
  haslach_interactionmatrix.transport_costs(
104
- ors_auth="5b3ce3597851110001cf62480a15aafdb5a64f4d91805929f8af6abd"
105
- #network=False,
99
+ ors_auth="5b3ce3597851110001cf62480a15aafdb5a64f4d91805929f8af6abd",
100
+ network=True,
106
101
  #distance_unit="meters",
107
102
  # set network = True to calculate transport costs matrix via ORS API (default)
108
103
  )
@@ -131,12 +126,10 @@ print(huff_model.get_market_areas_df())
131
126
 
132
127
  # Maximum Likelihood fit for Huff Model:
133
128
 
134
- haslach_interactionmatrix.ml_fit(
135
- #initial_params=[1, -2],
136
- initial_params=[1, 9, -0.6],
129
+ haslach_interactionmatrix.huff_ml_fit(
130
+ initial_params=[1, -2],
137
131
  method="trust-constr",
138
- #bounds = [(0.8, 0.9999),(-2.5, -1.5)],
139
- bounds = [(0.8, 0.9999),(7, 11),(-0.9, -0.4)],
132
+ bounds = [(0.8, 0.9999),(-2.5, -1.5)]
140
133
  )
141
134
  # Maximum Likelihood fit for Huff Model
142
135
 
@@ -212,14 +205,20 @@ Wieland2015_interaction_matrix = load_interaction_matrix(
212
205
  "K",
213
206
  "K_KKr"
214
207
  ],
208
+ market_size_col="Sum_Ek1",
209
+ flows_col="Anb_Eink1",
215
210
  transport_costs_col="Dist_Min2",
216
- probabilities_col="MA",
211
+ probabilities_col="MA_Anb1",
217
212
  data_type="xlsx"
218
213
  )
214
+ # Loading interaction matrix from XLSX file
219
215
 
220
216
  Wieland2015_interaction_matrix.summary()
221
217
  # Summary of interaction matrix
222
218
 
219
+
220
+ # Parameter estimation via MCI model:
221
+
223
222
  Wieland2015_fit = Wieland2015_interaction_matrix.mci_fit(
224
223
  cols=[
225
224
  "A_j",
@@ -240,6 +239,122 @@ Wieland2015_fit.summary()
240
239
  # MCI model summary
241
240
 
242
241
 
242
+ # Parameter estimation via Maximum Likelihood:
243
+
244
+ Wieland2015_interaction_matrix2 = load_interaction_matrix(
245
+ data="data/Wieland2015.xlsx",
246
+ customer_origins_col="Quellort",
247
+ supply_locations_col="Zielort",
248
+ attraction_col=[
249
+ "VF",
250
+ "K",
251
+ "K_KKr"
252
+ ],
253
+ market_size_col="Sum_Ek",
254
+ flows_col="Anb_Eink",
255
+ transport_costs_col="Dist_Min2",
256
+ probabilities_col="MA_Anb",
257
+ data_type="xlsx",
258
+ xlsx_sheet="interactionmatrix",
259
+ check_df_vars=False
260
+ )
261
+ # Loading empirical interaction matrix again
262
+
263
+ Wieland2015_interaction_matrix2.define_weightings(
264
+ vars_funcs = {
265
+ 0: {
266
+ "name": "A_j",
267
+ "func": "power"
268
+ },
269
+ 1: {
270
+ "name": "t_ij",
271
+ "func": "power",
272
+ #"func": "exponential"
273
+ #"func": "logistic"
274
+ },
275
+ 2: {
276
+ "name": "K",
277
+ "func": "power"
278
+ },
279
+ 3: {
280
+ "name": "K_KKr",
281
+ "func": "power"
282
+ }
283
+ }
284
+ )
285
+ # Defining weighting functions
286
+
287
+ Wieland2015_interaction_matrix2.huff_ml_fit(
288
+ # Power TC function
289
+ initial_params=[0.9, -1.5, 0.5, 0.3],
290
+ bounds=[(0.5, 1), (-2, -1), (0.2, 0.7), (0.2, 0.7)],
291
+ # # Logistic TC function:
292
+ # initial_params=[0.9, 10, -0.5, 0.5, 0.3],
293
+ # bounds=[(0.5, 1), (8, 12), (-0.7, -0.2), (0.2, 0.7), (0.2, 0.7)],
294
+ fit_by="probabilities",
295
+ #method = "trust-constr"
296
+ )
297
+ # ML fit with power transport cost function based on probabilities
298
+ # from InteractionMatrix object
299
+
300
+ Wieland2015_interaction_matrix2.summary()
301
+ # Summary of interaction matrix
302
+
303
+ huff_model_fit2 = Wieland2015_interaction_matrix2.marketareas()
304
+ # Calculation of market areas
305
+
306
+ huff_model_fit2 = huff_model_fit2.ml_fit(
307
+ # Power TC function
308
+ initial_params=[0.9, -1.5, 0.5, 0.3],
309
+ bounds=[(0.5, 1), (-2, -1), (0.2, 0.7), (0.2, 0.7)],
310
+ # # Logistic TC function:
311
+ # initial_params=[0.9, 10, -0.5, 0.5, 0.3],
312
+ # bounds=[(0.5, 1), (8, 12), (-0.7, -0.2), (0.2, 0.7), (0.2, 0.7)],
313
+ fit_by="probabilities",
314
+ #method = "trust-constr"
315
+ )
316
+ # ML fit with power transport cost function based on probabilities
317
+ # from HuffModel object
318
+
319
+ huff_model_fit2.summary()
320
+ # Summary of Hudd model
321
+
322
+
323
+ # Loading and including total market areas
324
+
325
+ Wieland2025_totalmarketareas = load_marketareas(
326
+ data="data/Wieland2015.xlsx",
327
+ supply_locations_col="Zielort",
328
+ total_col="Anb_Eink",
329
+ data_type="xlsx",
330
+ xlsx_sheet="total_marketareas"
331
+ )
332
+ # Loading empirical total market areas
333
+
334
+ huff_model_fit2 = Wieland2025_totalmarketareas.add_to_model(
335
+ huff_model_fit2
336
+ )
337
+ # Adding total market areas to HuffModel object
338
+
339
+ print(huff_model_fit2.get_market_areas_df())
340
+ # Showing total market areas of HuffModel object
341
+
342
+ huff_model_fit3 = huff_model_fit2.ml_fit(
343
+ # Power TC function
344
+ initial_params=[0.9, -1.5, 0.5, 0.3],
345
+ bounds=[(0.5, 1), (-2, -1), (0.2, 0.7), (0.2, 0.7)],
346
+ # # Logistic TC function:
347
+ # initial_params=[0.9, 10, -0.5, 0.5, 0.3],
348
+ # bounds=[(0.5, 1), (8, 12), (-0.7, -0.2), (0.2, 0.7), (0.2, 0.7)],
349
+ fit_by="totals",
350
+ #method = "trust-constr"
351
+ )
352
+ # Fit Huff model by totals
353
+
354
+ huff_model_fit3.summary()
355
+ # Show summary
356
+
357
+
243
358
  # Buffer analysis:
244
359
 
245
360
  Haslach_supermarkets_gdf = Haslach_supermarkets.get_geodata_gpd_original()
@@ -298,7 +413,8 @@ map_with_basemap(
298
413
  Haslach_supermarkets_gdf
299
414
  ],
300
415
  styles={
301
- 0: {"name": "Isochrones",
416
+ 0: {
417
+ "name": "Isochrones",
302
418
  "color": {
303
419
  "segm_min": {
304
420
  "3": "midnightblue",
@@ -310,11 +426,13 @@ map_with_basemap(
310
426
  },
311
427
  "alpha": 0.3
312
428
  },
313
- 1: {"name": "Districts",
429
+ 1: {
430
+ "name": "Districts",
314
431
  "color": "black",
315
432
  "alpha": 1
316
433
  },
317
- 2: {"name": "Supermarket chains",
434
+ 2: {
435
+ "name": "Supermarket chains",
318
436
  "color": {
319
437
  "Name": {
320
438
  "Aldi S├╝d": "blue",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: huff
3
- Version: 1.4.1
3
+ Version: 1.5.1
4
4
  Summary: huff: Huff Model Market Area Analysis
5
5
  Author: Thomas Wieland
6
6
  Author-email: geowieland@googlemail.com
@@ -28,14 +28,24 @@ Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geo
28
28
  See the /tests directory for usage examples of most of the included functions.
29
29
 
30
30
 
31
+ ## Updates v1.5.1
32
+ - Extensions:
33
+ - HuffModel.ml_fit(): Fit Huff model parameters by empirical total market areas
34
+ - HuffModel.summary(): Goodnes-of-fit depends on fit_by
35
+ - load_market_areas(): Loading table with totals and including into InteractionMatrix, HuffModel and MCIModel objects
36
+ - Bugfixes:
37
+ - InteractionMatrix.summary(): NoneType parameter
38
+ - InteractionMatrix.huff_ml_fit(): Update estimates possible even if fit algorithm did not converge
39
+
40
+
31
41
  ## Features
32
42
 
33
43
  - **Huff Model**:
34
44
  - Defining origins and destinations with weightings
35
45
  - Creating interaction matrix from origins and destinations
36
- - Market simulation with basic Huff Model
37
46
  - Different function types: power, exponential, logistic
38
- - Huff model parameter estimation via Maximum Likelihood (ML)
47
+ - Huff model parameter estimation via Maximum Likelihood (ML) by probalities and customer flows
48
+ - Huff model market simulation
39
49
  - **Multiplicative Competitive Interaction Model**:
40
50
  - Log-centering transformation of interaction matrix
41
51
  - Fitting MCI model with >= 2 independent variables
@@ -1,10 +1,10 @@
1
1
  huff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  huff/gistools.py,sha256=fgeE1IsUO7UIaawb23kuiz_Rlxn7T18iLLTA5yvgp74,7038
3
- huff/models.py,sha256=3IxZLUp8-sC-sy0qJ677-cYEi09cqNOuOw_QBvr-K5s,89975
3
+ huff/models.py,sha256=IihaZmutJjdKqzTVXGVmcYbauFJImF-UPsZ2QCPzw8s,125182
4
4
  huff/ors.py,sha256=JlO2UEishQX87PIiktksOrVT5QdB-GEWgjXcxoR_KuA,11929
5
5
  huff/osm.py,sha256=9A-7hxeZyjA2r8w2_IqqwH14qq2Y9AS1GxVKOD7utqs,7747
6
6
  huff/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- huff/tests/tests_huff.py,sha256=nnOcZmhvEQMsnCf7YKnm-2vAY_h7FA7p7E2UPBDXLRU,9435
7
+ huff/tests/tests_huff.py,sha256=eHnEiV8m7TjpAXnJqo1aZ0YlQCGHxK1iFXROEyhN5cU,12884
8
8
  huff/tests/data/Haslach.cpg,sha256=OtMDH1UDpEBK-CUmLugjLMBNTqZoPULF3QovKiesmCQ,5
9
9
  huff/tests/data/Haslach.dbf,sha256=GVPIt05OzDO7UrRDcsMhiYWvyXAPg6Z-qkiysFzj-fc,506
10
10
  huff/tests/data/Haslach.prj,sha256=2Jy1Vlzh7UxQ1MXpZ9UYLs2SxfrObj2xkEkZyLqmGTY,437
@@ -23,8 +23,8 @@ huff/tests/data/Haslach_supermarkets.prj,sha256=2Jy1Vlzh7UxQ1MXpZ9UYLs2SxfrObj2x
23
23
  huff/tests/data/Haslach_supermarkets.qmd,sha256=JlcOYzG4vI1NH1IuOpxwIPnJsCyC-pDRAI00TzEvNf0,2522
24
24
  huff/tests/data/Haslach_supermarkets.shp,sha256=X7QbQ0BTMag_B-bDRbpr-go2BQIXo3Y8zMAKpYZmlps,324
25
25
  huff/tests/data/Haslach_supermarkets.shx,sha256=j23QHX-SmdAeN04rw0x8nUOran-OCg_T6r_LvzzEPWs,164
26
- huff/tests/data/Wieland2015.xlsx,sha256=SaVM-Hi5dBTmf2bzszMnZ2Ec8NUE05S_5F2lQj0ayS0,19641
27
- huff-1.4.1.dist-info/METADATA,sha256=TMOldW_srTquKEghHkuMKyofG2MjUMUV4OKfdNUyFoU,5692
28
- huff-1.4.1.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
29
- huff-1.4.1.dist-info/top_level.txt,sha256=nlzX-PxZNFmIxANIJMySuIFPihd6qOBkRlhIC28NEsQ,5
30
- huff-1.4.1.dist-info/RECORD,,
26
+ huff/tests/data/Wieland2015.xlsx,sha256=jUt9YcRrYL99AjxzXKMXD3o5erjd9r_jYfnALdrTQ3o,24333
27
+ huff-1.5.1.dist-info/METADATA,sha256=BXRKyUp5qIEoYjNpo_w9zpUwMTDTO_aegNgr67qj8ns,6187
28
+ huff-1.5.1.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
29
+ huff-1.5.1.dist-info/top_level.txt,sha256=nlzX-PxZNFmIxANIJMySuIFPihd6qOBkRlhIC28NEsQ,5
30
+ huff-1.5.1.dist-info/RECORD,,
File without changes