huff 1.5.3__tar.gz → 1.5.4__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.
Files changed (36) hide show
  1. {huff-1.5.3 → huff-1.5.4}/PKG-INFO +4 -6
  2. {huff-1.5.3 → huff-1.5.4}/README.md +3 -5
  3. {huff-1.5.3 → huff-1.5.4}/huff/models.py +93 -58
  4. {huff-1.5.3 → huff-1.5.4}/huff/tests/tests_huff.py +2 -2
  5. {huff-1.5.3 → huff-1.5.4}/huff.egg-info/PKG-INFO +4 -6
  6. {huff-1.5.3 → huff-1.5.4}/setup.py +1 -1
  7. {huff-1.5.3 → huff-1.5.4}/MANIFEST.in +0 -0
  8. {huff-1.5.3 → huff-1.5.4}/huff/__init__.py +0 -0
  9. {huff-1.5.3 → huff-1.5.4}/huff/gistools.py +0 -0
  10. {huff-1.5.3 → huff-1.5.4}/huff/ors.py +0 -0
  11. {huff-1.5.3 → huff-1.5.4}/huff/osm.py +0 -0
  12. {huff-1.5.3 → huff-1.5.4}/huff/tests/__init__.py +0 -0
  13. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach.cpg +0 -0
  14. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach.dbf +0 -0
  15. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach.prj +0 -0
  16. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach.qmd +0 -0
  17. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach.shp +0 -0
  18. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach.shx +0 -0
  19. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_new_supermarket.cpg +0 -0
  20. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_new_supermarket.dbf +0 -0
  21. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_new_supermarket.prj +0 -0
  22. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_new_supermarket.qmd +0 -0
  23. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_new_supermarket.shp +0 -0
  24. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_new_supermarket.shx +0 -0
  25. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_supermarkets.cpg +0 -0
  26. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_supermarkets.dbf +0 -0
  27. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_supermarkets.prj +0 -0
  28. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_supermarkets.qmd +0 -0
  29. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_supermarkets.shp +0 -0
  30. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Haslach_supermarkets.shx +0 -0
  31. {huff-1.5.3 → huff-1.5.4}/huff/tests/data/Wieland2015.xlsx +0 -0
  32. {huff-1.5.3 → huff-1.5.4}/huff.egg-info/SOURCES.txt +0 -0
  33. {huff-1.5.3 → huff-1.5.4}/huff.egg-info/dependency_links.txt +0 -0
  34. {huff-1.5.3 → huff-1.5.4}/huff.egg-info/requires.txt +0 -0
  35. {huff-1.5.3 → huff-1.5.4}/huff.egg-info/top_level.txt +0 -0
  36. {huff-1.5.3 → huff-1.5.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: huff
3
- Version: 1.5.3
3
+ Version: 1.5.4
4
4
  Summary: huff: Huff Model Market Area Analysis
5
5
  Author: Thomas Wieland
6
6
  Author-email: geowieland@googlemail.com
@@ -18,12 +18,10 @@ Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geo
18
18
  See the /tests directory for usage examples of most of the included functions.
19
19
 
20
20
 
21
- ## Updates v1.5.3
21
+ ## Updates v1.5.4
22
22
  - Bugfixes:
23
- - InteractionMatrix.summary() and HuffModel.summary(): No KeyError when param is None anymore
24
- - Extensions:
25
- - Confidence intervals (bootstrap) for Huff Model ML estimations
26
- - ValueError and KeyError are more precise (function is included)
23
+ - Use of check_vars() is now optional (default: True)
24
+ - Correction of args argument when calling minimize() in huff_ml_fit()
27
25
 
28
26
 
29
27
  ## Features
@@ -10,12 +10,10 @@ Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geo
10
10
  See the /tests directory for usage examples of most of the included functions.
11
11
 
12
12
 
13
- ## Updates v1.5.3
13
+ ## Updates v1.5.4
14
14
  - Bugfixes:
15
- - InteractionMatrix.summary() and HuffModel.summary(): No KeyError when param is None anymore
16
- - Extensions:
17
- - Confidence intervals (bootstrap) for Huff Model ML estimations
18
- - ValueError and KeyError are more precise (function is included)
15
+ - Use of check_vars() is now optional (default: True)
16
+ - Correction of args argument when calling minimize() in huff_ml_fit()
19
17
 
20
18
 
21
19
  ## Features
@@ -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.5.3
8
- # Last update: 2025-07-15 17:22
7
+ # Version: 1.5.4
8
+ # Last update: 2025-07-18 18:07
9
9
  # Copyright (c) 2025 Thomas Wieland
10
10
  #-----------------------------------------------------------------------
11
11
 
@@ -766,7 +766,10 @@ class InteractionMatrix:
766
766
  self.supply_locations.metadata = supply_locations_metadata
767
767
  self.customer_origins.metadata = customer_origins_metadata
768
768
 
769
- def utility(self):
769
+ def utility(
770
+ self,
771
+ check_df_vars: bool = True
772
+ ):
770
773
 
771
774
  interaction_matrix_df = self.interaction_matrix_df
772
775
 
@@ -781,10 +784,11 @@ class InteractionMatrix:
781
784
  if interaction_matrix_df["A_j"].isna().all():
782
785
  raise ValueError ("Error in utility calculation: Attraction variable is not defined")
783
786
 
784
- check_vars(
785
- df = interaction_matrix_df,
786
- cols = ["A_j", "t_ij"]
787
- )
787
+ if check_df_vars:
788
+ check_vars(
789
+ df = interaction_matrix_df,
790
+ cols = ["A_j", "t_ij"]
791
+ )
788
792
 
789
793
  customer_origins = self.customer_origins
790
794
  customer_origins_metadata = customer_origins.get_metadata()
@@ -793,9 +797,9 @@ class InteractionMatrix:
793
797
  if tc_weighting["func"] == "power":
794
798
  interaction_matrix_df["t_ij_weighted"] = interaction_matrix_df["t_ij"] ** tc_weighting["param"]
795
799
  elif tc_weighting["func"] == "exponential":
796
- interaction_matrix_df["t_ij_weighted"] = np.exp(tc_weighting["param"] * interaction_matrix_df['t_ij'])
800
+ interaction_matrix_df["t_ij_weighted"] = np.exp(tc_weighting["param"] * interaction_matrix_df["t_ij"])
797
801
  elif tc_weighting["func"] == "logistic":
798
- interaction_matrix_df["t_ij_weighted"] = 1+np.exp(tc_weighting["param"][0] + tc_weighting["param"][1] * interaction_matrix_df['t_ij'])
802
+ interaction_matrix_df["t_ij_weighted"] = 1+np.exp(tc_weighting["param"][0] + tc_weighting["param"][1] * interaction_matrix_df["t_ij"])
799
803
  else:
800
804
  raise ValueError ("Error in utility calculation: Transport costs weighting is not defined.")
801
805
 
@@ -818,8 +822,8 @@ class InteractionMatrix:
818
822
 
819
823
  for key, attrac_var in enumerate(attrac_vars):
820
824
 
821
- attrac_var_key = key #+1
822
- if attrac_var_key == 0: #1:
825
+ attrac_var_key = key
826
+ if attrac_var_key == 0:
823
827
  continue
824
828
 
825
829
  name = supply_locations_metadata["weighting"][attrac_var_key]["name"]
@@ -850,7 +854,10 @@ class InteractionMatrix:
850
854
 
851
855
  return self
852
856
 
853
- def probabilities (self):
857
+ def probabilities (
858
+ self,
859
+ check_df_vars: bool = True
860
+ ):
854
861
 
855
862
  interaction_matrix_df = self.interaction_matrix_df
856
863
 
@@ -858,6 +865,12 @@ class InteractionMatrix:
858
865
  self.utility()
859
866
  interaction_matrix_df = self.interaction_matrix_df
860
867
 
868
+ if check_df_vars:
869
+ check_vars(
870
+ df = interaction_matrix_df,
871
+ cols = ["U_ij"]
872
+ )
873
+
861
874
  utility_i = pd.DataFrame(interaction_matrix_df.groupby("i")["U_ij"].sum())
862
875
  utility_i = utility_i.rename(columns = {"U_ij": "U_i"})
863
876
 
@@ -876,7 +889,10 @@ class InteractionMatrix:
876
889
 
877
890
  return self
878
891
 
879
- def flows (self):
892
+ def flows (
893
+ self,
894
+ check_df_vars: bool = True
895
+ ):
880
896
 
881
897
  interaction_matrix_df = self.interaction_matrix_df
882
898
 
@@ -885,10 +901,11 @@ class InteractionMatrix:
885
901
  if interaction_matrix_df["C_i"].isna().all():
886
902
  raise ValueError ("Error in flows calculation: Market size column in customer origins not defined. Use CustomerOrigins.define_marketsize()")
887
903
 
888
- check_vars(
889
- df = interaction_matrix_df,
890
- cols = ["C_i"]
891
- )
904
+ if check_df_vars:
905
+ check_vars(
906
+ df = interaction_matrix_df,
907
+ cols = ["C_i"]
908
+ )
892
909
 
893
910
  if interaction_matrix_df["p_ij"].isna().all():
894
911
  self.probabilities()
@@ -900,15 +917,19 @@ class InteractionMatrix:
900
917
 
901
918
  return self
902
919
 
903
- def marketareas(self):
920
+ def marketareas(
921
+ self,
922
+ check_df_vars: bool = True
923
+ ):
904
924
 
905
925
  interaction_matrix_df = self.interaction_matrix_df
906
926
 
907
- check_vars(
908
- df = interaction_matrix_df,
909
- cols = ["E_ij"],
910
- check_zero = False
911
- )
927
+ if check_df_vars:
928
+ check_vars(
929
+ df = interaction_matrix_df,
930
+ cols = ["E_ij"],
931
+ check_zero = False
932
+ )
912
933
 
913
934
  market_areas_df = pd.DataFrame(interaction_matrix_df.groupby("j")["E_ij"].sum())
914
935
  market_areas_df = market_areas_df.reset_index(drop=False)
@@ -947,9 +968,9 @@ class InteractionMatrix:
947
968
  if tc_weighting["func"] == "power":
948
969
  interaction_matrix_df["t_ij_weighted"] = interaction_matrix_df["t_ij"] ** tc_weighting["param"]
949
970
  elif tc_weighting["func"] == "exponential":
950
- interaction_matrix_df["t_ij_weighted"] = np.exp(tc_weighting["param"] * interaction_matrix_df['t_ij'])
971
+ interaction_matrix_df["t_ij_weighted"] = np.exp(tc_weighting["param"] * interaction_matrix_df["t_ij"])
951
972
  elif tc_weighting["func"] == "logistic":
952
- interaction_matrix_df["t_ij_weighted"] = 1+np.exp(tc_weighting["param"][0] + tc_weighting["param"][1] * interaction_matrix_df['t_ij'])
973
+ interaction_matrix_df["t_ij_weighted"] = 1+np.exp(tc_weighting["param"][0] + tc_weighting["param"][1] * interaction_matrix_df["t_ij"])
953
974
  else:
954
975
  raise ValueError ("Error in hansen accessibility calculation: Transport costs weighting is not defined.")
955
976
 
@@ -1073,7 +1094,8 @@ class InteractionMatrix:
1073
1094
  def loglik(
1074
1095
  self,
1075
1096
  params,
1076
- fit_by = "probabilities"
1097
+ fit_by = "probabilities",
1098
+ check_df_vars: bool = True
1077
1099
  ):
1078
1100
 
1079
1101
  if fit_by not in ["probabilities", "flows"]:
@@ -1160,9 +1182,9 @@ class InteractionMatrix:
1160
1182
 
1161
1183
  interaction_matrix_copy = copy.deepcopy(self)
1162
1184
 
1163
- interaction_matrix_copy.utility()
1164
- interaction_matrix_copy.probabilities()
1165
- interaction_matrix_copy.flows()
1185
+ interaction_matrix_copy.utility(check_df_vars = check_df_vars)
1186
+ interaction_matrix_copy.probabilities(check_df_vars = check_df_vars)
1187
+ interaction_matrix_copy.flows(check_df_vars = check_df_vars)
1166
1188
 
1167
1189
  interaction_matrix_df_copy = interaction_matrix_copy.get_interaction_matrix_df()
1168
1190
 
@@ -1196,7 +1218,8 @@ class InteractionMatrix:
1196
1218
  bounds: list = [(0.5, 1), (-3, -1)],
1197
1219
  constraints: list = [],
1198
1220
  fit_by = "probabilities",
1199
- update_estimates: bool = True
1221
+ update_estimates: bool = True,
1222
+ check_df_vars: bool = True
1200
1223
  ):
1201
1224
 
1202
1225
  supply_locations = self.supply_locations
@@ -1232,7 +1255,7 @@ class InteractionMatrix:
1232
1255
  ml_result = minimize(
1233
1256
  self.loglik,
1234
1257
  initial_params,
1235
- args=fit_by,
1258
+ args=(fit_by, check_df_vars),
1236
1259
  method = method,
1237
1260
  bounds = bounds,
1238
1261
  constraints = constraints,
@@ -1745,7 +1768,8 @@ class HuffModel:
1745
1768
 
1746
1769
  def loglik(
1747
1770
  self,
1748
- params
1771
+ params,
1772
+ check_df_vars: bool = True
1749
1773
  ):
1750
1774
 
1751
1775
  if not isinstance(params, list):
@@ -1827,9 +1851,9 @@ class HuffModel:
1827
1851
 
1828
1852
  interaction_matrix_copy = copy.deepcopy(huff_model_copy.interaction_matrix)
1829
1853
 
1830
- interaction_matrix_copy = interaction_matrix_copy.utility()
1831
- interaction_matrix_copy = interaction_matrix_copy.probabilities()
1832
- interaction_matrix_copy = interaction_matrix_copy.flows()
1854
+ interaction_matrix_copy = interaction_matrix_copy.utility(check_df_vars = check_df_vars)
1855
+ interaction_matrix_copy = interaction_matrix_copy.probabilities(check_df_vars = check_df_vars)
1856
+ interaction_matrix_copy = interaction_matrix_copy.flows(check_df_vars = check_df_vars)
1833
1857
 
1834
1858
  huff_model_copy = interaction_matrix_copy.marketareas()
1835
1859
 
@@ -1855,7 +1879,8 @@ class HuffModel:
1855
1879
  constraints: list = [],
1856
1880
  fit_by = "probabilities",
1857
1881
  update_estimates: bool = True,
1858
- check_numbers: bool = True
1882
+ check_numbers: bool = True,
1883
+ check_df_vars: bool = True
1859
1884
  ):
1860
1885
 
1861
1886
  if fit_by in ["probabilities", "flows"]:
@@ -1866,7 +1891,8 @@ class HuffModel:
1866
1891
  bounds = bounds,
1867
1892
  constraints = constraints,
1868
1893
  fit_by = fit_by,
1869
- update_estimates = update_estimates
1894
+ update_estimates = update_estimates,
1895
+ check_df_vars = check_df_vars
1870
1896
  )
1871
1897
 
1872
1898
  elif fit_by == "totals":
@@ -1914,6 +1940,7 @@ class HuffModel:
1914
1940
  ml_result = minimize(
1915
1941
  self.loglik,
1916
1942
  initial_params,
1943
+ args=check_df_vars,
1917
1944
  method = method,
1918
1945
  bounds = bounds,
1919
1946
  constraints = constraints,
@@ -1999,11 +2026,11 @@ class HuffModel:
1999
2026
 
2000
2027
  else:
2001
2028
 
2002
- self.interaction_matrix.utility()
2003
- self.interaction_matrix.probabilities()
2004
- self.interaction_matrix.flows()
2029
+ self.interaction_matrix.utility(check_df_vars = check_df_vars)
2030
+ self.interaction_matrix.probabilities(check_df_vars = check_df_vars)
2031
+ self.interaction_matrix.flows(check_df_vars = check_df_vars)
2005
2032
 
2006
- huff_model_new_marketareas = self.interaction_matrix.marketareas()
2033
+ huff_model_new_marketareas = self.interaction_matrix.marketareas(check_df_vars = check_df_vars)
2007
2034
  self.market_areas_df["T_j"] = huff_model_new_marketareas.get_market_areas_df()["T_j"]
2008
2035
 
2009
2036
  self.interaction_matrix.metadata["fit"] = {
@@ -2372,7 +2399,8 @@ class MCIModel:
2372
2399
 
2373
2400
  def utility(
2374
2401
  self,
2375
- transformation = "LCT"
2402
+ transformation = "LCT",
2403
+ check_df_vars: bool = True
2376
2404
  ):
2377
2405
 
2378
2406
  interaction_matrix = self.interaction_matrix
@@ -2384,10 +2412,11 @@ class MCIModel:
2384
2412
  if interaction_matrix_df["A_j"].isna().all():
2385
2413
  raise ValueError ("Error in utility calculation: Attraction variable is not defined")
2386
2414
 
2387
- check_vars(
2388
- df = interaction_matrix_df,
2389
- cols = ["A_j", "t_ij"]
2390
- )
2415
+ if check_df_vars:
2416
+ check_vars(
2417
+ df = interaction_matrix_df,
2418
+ cols = ["A_j", "t_ij"]
2419
+ )
2391
2420
 
2392
2421
  customer_origins = interaction_matrix.get_customer_origins()
2393
2422
  customer_origins_metadata = customer_origins.get_metadata()
@@ -2476,7 +2505,8 @@ class MCIModel:
2476
2505
 
2477
2506
  def flows (
2478
2507
  self,
2479
- transformation = "LCT"
2508
+ transformation = "LCT",
2509
+ check_df_vars: bool = True
2480
2510
  ):
2481
2511
 
2482
2512
  interaction_matrix = self.interaction_matrix
@@ -2488,10 +2518,11 @@ class MCIModel:
2488
2518
  if interaction_matrix_df["C_i"].isna().all():
2489
2519
  raise ValueError ("Error in flows calculation: Market size column in customer origins not defined. Use CustomerOrigins.define_marketsize()")
2490
2520
 
2491
- check_vars(
2492
- df = interaction_matrix_df,
2493
- cols = ["C_i"]
2494
- )
2521
+ if check_df_vars:
2522
+ check_vars(
2523
+ df = interaction_matrix_df,
2524
+ cols = ["C_i"]
2525
+ )
2495
2526
 
2496
2527
  if interaction_matrix_df["p_ij"].isna().all():
2497
2528
  self.probabilities(transformation=transformation)
@@ -2504,15 +2535,19 @@ class MCIModel:
2504
2535
 
2505
2536
  return self
2506
2537
 
2507
- def marketareas (self):
2538
+ def marketareas (
2539
+ self,
2540
+ check_df_vars: bool = True
2541
+ ):
2508
2542
 
2509
2543
  interaction_matrix = self.interaction_matrix
2510
2544
  interaction_matrix_df = interaction_matrix.get_interaction_matrix_df()
2511
2545
 
2512
- check_vars(
2513
- df = interaction_matrix_df,
2514
- cols = ["E_ij"]
2515
- )
2546
+ if check_df_vars:
2547
+ check_vars(
2548
+ df = interaction_matrix_df,
2549
+ cols = ["E_ij"]
2550
+ )
2516
2551
 
2517
2552
  market_areas_df = pd.DataFrame(interaction_matrix_df.groupby("j")["E_ij"].sum())
2518
2553
  market_areas_df = market_areas_df.reset_index(drop=False)
@@ -2735,7 +2770,7 @@ def load_interaction_matrix(
2735
2770
  xlsx_sheet: str = None,
2736
2771
  crs_input = "EPSG:4326",
2737
2772
  crs_output = "EPSG:4326",
2738
- check_df_vars = True
2773
+ check_df_vars: bool = True
2739
2774
  ):
2740
2775
 
2741
2776
  if isinstance(data, pd.DataFrame):
@@ -2976,7 +3011,7 @@ def load_marketareas(
2976
3011
  csv_decimal = ",",
2977
3012
  csv_encoding="unicode_escape",
2978
3013
  xlsx_sheet: str = None,
2979
- check_df_vars = True
3014
+ check_df_vars: bool = True
2980
3015
  ):
2981
3016
 
2982
3017
  if isinstance(data, pd.DataFrame):
@@ -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.5.3
8
- # Last update: 2025-07-15 17:22
7
+ # Version: 1.5.4
8
+ # Last update: 2025-07-18 18:06
9
9
  # Copyright (c) 2025 Thomas Wieland
10
10
  #-----------------------------------------------------------------------
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: huff
3
- Version: 1.5.3
3
+ Version: 1.5.4
4
4
  Summary: huff: Huff Model Market Area Analysis
5
5
  Author: Thomas Wieland
6
6
  Author-email: geowieland@googlemail.com
@@ -18,12 +18,10 @@ Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geo
18
18
  See the /tests directory for usage examples of most of the included functions.
19
19
 
20
20
 
21
- ## Updates v1.5.3
21
+ ## Updates v1.5.4
22
22
  - Bugfixes:
23
- - InteractionMatrix.summary() and HuffModel.summary(): No KeyError when param is None anymore
24
- - Extensions:
25
- - Confidence intervals (bootstrap) for Huff Model ML estimations
26
- - ValueError and KeyError are more precise (function is included)
23
+ - Use of check_vars() is now optional (default: True)
24
+ - Correction of args argument when calling minimize() in huff_ml_fit()
27
25
 
28
26
 
29
27
  ## Features
@@ -7,7 +7,7 @@ def read_README():
7
7
 
8
8
  setup(
9
9
  name='huff',
10
- version='1.5.3',
10
+ version='1.5.4',
11
11
  description='huff: Huff Model Market Area Analysis',
12
12
  packages=find_packages(include=["huff", "huff.tests"]),
13
13
  include_package_data=True,
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