huff 1.5.1__tar.gz → 1.5.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.5.1 → huff-1.5.2}/PKG-INFO +5 -9
- {huff-1.5.1 → huff-1.5.2}/README.md +4 -8
- {huff-1.5.1 → huff-1.5.2}/huff/models.py +40 -37
- huff-1.5.2/huff/tests/data/Wieland2015.xlsx +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/tests_huff.py +5 -2
- {huff-1.5.1 → huff-1.5.2}/huff.egg-info/PKG-INFO +5 -9
- {huff-1.5.1 → huff-1.5.2}/setup.py +1 -1
- huff-1.5.1/huff/tests/data/Wieland2015.xlsx +0 -0
- {huff-1.5.1 → huff-1.5.2}/MANIFEST.in +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/__init__.py +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/gistools.py +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/ors.py +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/osm.py +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/__init__.py +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach.cpg +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach.dbf +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach.prj +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach.qmd +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach.shp +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach.shx +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_new_supermarket.cpg +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_new_supermarket.dbf +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_new_supermarket.prj +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_new_supermarket.qmd +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_new_supermarket.shp +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_new_supermarket.shx +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_supermarkets.cpg +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_supermarkets.dbf +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_supermarkets.prj +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_supermarkets.qmd +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_supermarkets.shp +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff/tests/data/Haslach_supermarkets.shx +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff.egg-info/SOURCES.txt +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff.egg-info/dependency_links.txt +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff.egg-info/requires.txt +0 -0
- {huff-1.5.1 → huff-1.5.2}/huff.egg-info/top_level.txt +0 -0
- {huff-1.5.1 → huff-1.5.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: huff
|
3
|
-
Version: 1.5.
|
3
|
+
Version: 1.5.2
|
4
4
|
Summary: huff: Huff Model Market Area Analysis
|
5
5
|
Author: Thomas Wieland
|
6
6
|
Author-email: geowieland@googlemail.com
|
@@ -18,14 +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.
|
22
|
-
- Extensions:
|
23
|
-
- HuffModel.ml_fit(): Fit Huff model parameters by empirical total market areas
|
24
|
-
- HuffModel.summary(): Goodnes-of-fit depends on fit_by
|
25
|
-
- load_market_areas(): Loading table with totals and including into InteractionMatrix, HuffModel and MCIModel objects
|
21
|
+
## Updates v1.5.2
|
26
22
|
- Bugfixes:
|
27
|
-
-
|
28
|
-
-
|
23
|
+
- HuffModel.ml_fit(): Correct values of expected T_j, corrected calculation of model fit metrices when fit_by="totals"
|
24
|
+
- HuffModel.ml_fit(): Check if sum of E_ij != sum of T_j
|
29
25
|
|
30
26
|
|
31
27
|
## Features
|
@@ -34,7 +30,7 @@ See the /tests directory for usage examples of most of the included functions.
|
|
34
30
|
- Defining origins and destinations with weightings
|
35
31
|
- Creating interaction matrix from origins and destinations
|
36
32
|
- Different function types: power, exponential, logistic
|
37
|
-
- Huff model parameter estimation via Maximum Likelihood (ML) by probalities and
|
33
|
+
- Huff model parameter estimation via Maximum Likelihood (ML) by probalities, customer flows, and total market areas
|
38
34
|
- Huff model market simulation
|
39
35
|
- **Multiplicative Competitive Interaction Model**:
|
40
36
|
- Log-centering transformation of interaction matrix
|
@@ -10,14 +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.
|
14
|
-
- Extensions:
|
15
|
-
- HuffModel.ml_fit(): Fit Huff model parameters by empirical total market areas
|
16
|
-
- HuffModel.summary(): Goodnes-of-fit depends on fit_by
|
17
|
-
- load_market_areas(): Loading table with totals and including into InteractionMatrix, HuffModel and MCIModel objects
|
13
|
+
## Updates v1.5.2
|
18
14
|
- Bugfixes:
|
19
|
-
-
|
20
|
-
-
|
15
|
+
- HuffModel.ml_fit(): Correct values of expected T_j, corrected calculation of model fit metrices when fit_by="totals"
|
16
|
+
- HuffModel.ml_fit(): Check if sum of E_ij != sum of T_j
|
21
17
|
|
22
18
|
|
23
19
|
## Features
|
@@ -26,7 +22,7 @@ See the /tests directory for usage examples of most of the included functions.
|
|
26
22
|
- Defining origins and destinations with weightings
|
27
23
|
- Creating interaction matrix from origins and destinations
|
28
24
|
- Different function types: power, exponential, logistic
|
29
|
-
- Huff model parameter estimation via Maximum Likelihood (ML) by probalities and
|
25
|
+
- Huff model parameter estimation via Maximum Likelihood (ML) by probalities, customer flows, and total market areas
|
30
26
|
- Huff model market simulation
|
31
27
|
- **Multiplicative Competitive Interaction Model**:
|
32
28
|
- Log-centering transformation of interaction matrix
|
@@ -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.
|
8
|
-
# Last update: 2025-07-
|
7
|
+
# Version: 1.5.2
|
8
|
+
# Last update: 2025-07-02 21:09
|
9
9
|
# Copyright (c) 2025 Thomas Wieland
|
10
10
|
#-----------------------------------------------------------------------
|
11
11
|
|
@@ -1292,21 +1292,6 @@ class InteractionMatrix:
|
|
1292
1292
|
print(f"Optimization via {method} algorithm succeeded with parameters: {', '.join(str(round(par, 3)) for par in param_results)}.")
|
1293
1293
|
|
1294
1294
|
else:
|
1295
|
-
|
1296
|
-
# param_gamma = None
|
1297
|
-
# param_lambda = None
|
1298
|
-
|
1299
|
-
# supply_locations_metadata["weighting"][0]["param"] = param_gamma
|
1300
|
-
|
1301
|
-
# if customer_origins_metadata["weighting"][0]["func"] == "logistic":
|
1302
|
-
|
1303
|
-
# param_lambda2 = None
|
1304
|
-
# customer_origins_metadata["weighting"][0]["param"][0] = param_lambda
|
1305
|
-
# customer_origins_metadata["weighting"][0]["param"][1] = param_lambda2
|
1306
|
-
|
1307
|
-
# else:
|
1308
|
-
|
1309
|
-
# customer_origins_metadata["weighting"][0]["param"] = param_lambda
|
1310
1295
|
|
1311
1296
|
print(f"Optimiziation via {method} algorithm failed with error message: '{ml_result.message}'. See https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html for all available algorithms.")
|
1312
1297
|
|
@@ -1316,20 +1301,28 @@ class InteractionMatrix:
|
|
1316
1301
|
if update_estimates:
|
1317
1302
|
|
1318
1303
|
if "p_ij_emp" not in self.interaction_matrix_df.columns:
|
1304
|
+
|
1319
1305
|
self.interaction_matrix_df["p_ij_emp"] = self.interaction_matrix_df["p_ij"]
|
1320
|
-
|
1306
|
+
|
1307
|
+
print("NOTE: Probabilities in interaction matrix are treated as empirical probabilities")
|
1308
|
+
|
1321
1309
|
else:
|
1322
|
-
|
1310
|
+
|
1311
|
+
print("NOTE: Interaction matrix contains empirical probabilities")
|
1323
1312
|
|
1324
1313
|
if "E_ij_emp" not in self.interaction_matrix_df.columns:
|
1314
|
+
|
1325
1315
|
self.interaction_matrix_df["E_ij_emp"] = self.interaction_matrix_df["E_ij"]
|
1326
|
-
|
1316
|
+
|
1317
|
+
print("NOTE: Customer interactions in interaction matrix are treated as empirical interactions")
|
1318
|
+
|
1327
1319
|
else:
|
1328
|
-
|
1320
|
+
|
1321
|
+
print("NOTE: Interaction matrix contains empirical customer interactions")
|
1329
1322
|
|
1330
1323
|
if np.isnan(ml_result.x).any():
|
1331
1324
|
|
1332
|
-
print("No update of estimates because fit parameters contain NaN")
|
1325
|
+
print("WARNING: No update of estimates because fit parameters contain NaN")
|
1333
1326
|
|
1334
1327
|
update_estimates = False
|
1335
1328
|
|
@@ -1391,7 +1384,7 @@ class InteractionMatrix:
|
|
1391
1384
|
|
1392
1385
|
if "transport_costs" not in interaction_matrix_metadata:
|
1393
1386
|
|
1394
|
-
print("New destination(s) included. No transport costs calculation because not defined in original interaction matrix.")
|
1387
|
+
print("WARNING: New destination(s) included. No transport costs calculation because not defined in original interaction matrix.")
|
1395
1388
|
|
1396
1389
|
interaction_matrix_df = pd.concat(
|
1397
1390
|
[
|
@@ -1625,7 +1618,6 @@ class HuffModel:
|
|
1625
1618
|
print ("Goodness-of-fit for " + interaction_matrix_metadata["fit"]["fit_by"])
|
1626
1619
|
|
1627
1620
|
print("Sum of squared residuals ", round(huff_modelfit[1]["SQR"], 2))
|
1628
|
-
print("Sum of squares ", round(huff_modelfit[1]["SQT"], 2))
|
1629
1621
|
print("R-squared ", round(huff_modelfit[1]["Rsq"], 2))
|
1630
1622
|
print("Mean squared error ", round(huff_modelfit[1]["MSE"], 2))
|
1631
1623
|
print("Root mean squared error ", round(huff_modelfit[1]["RMSE"], 2))
|
@@ -1853,7 +1845,8 @@ class HuffModel:
|
|
1853
1845
|
bounds: list = [(0.5, 1), (-3, -1)],
|
1854
1846
|
constraints: list = [],
|
1855
1847
|
fit_by = "probabilities",
|
1856
|
-
update_estimates: bool = True
|
1848
|
+
update_estimates: bool = True,
|
1849
|
+
check_numbers: bool = True
|
1857
1850
|
):
|
1858
1851
|
|
1859
1852
|
if fit_by in ["probabilities", "flows"]:
|
@@ -1869,6 +1862,16 @@ class HuffModel:
|
|
1869
1862
|
|
1870
1863
|
elif fit_by == "totals":
|
1871
1864
|
|
1865
|
+
if check_numbers:
|
1866
|
+
|
1867
|
+
market_areas_df = self.market_areas_df
|
1868
|
+
interaction_matrix_df = self.get_interaction_matrix_df()
|
1869
|
+
T_j_market_areas_df = sum(market_areas_df["T_j"])
|
1870
|
+
T_j_interaction_matrix_df = sum(interaction_matrix_df["E_ij"])
|
1871
|
+
|
1872
|
+
if T_j_market_areas_df != T_j_interaction_matrix_df:
|
1873
|
+
print("WARNING: Sum of total market areas (" + str(int(T_j_market_areas_df)) + ") is not equal to sum of customer flows (" + str(int(T_j_interaction_matrix_df)) + ")")
|
1874
|
+
|
1872
1875
|
supply_locations = self.interaction_matrix.supply_locations
|
1873
1876
|
supply_locations_metadata = supply_locations.get_metadata()
|
1874
1877
|
|
@@ -1986,12 +1989,13 @@ class HuffModel:
|
|
1986
1989
|
update_estimates = False
|
1987
1990
|
|
1988
1991
|
else:
|
1989
|
-
|
1992
|
+
|
1990
1993
|
self.interaction_matrix.utility()
|
1991
1994
|
self.interaction_matrix.probabilities()
|
1992
|
-
self.interaction_matrix.flows()
|
1995
|
+
self.interaction_matrix.flows()
|
1993
1996
|
|
1994
|
-
self.interaction_matrix.marketareas()
|
1997
|
+
huff_model_new_marketareas = self.interaction_matrix.marketareas()
|
1998
|
+
self.market_areas_df["T_j"] = huff_model_new_marketareas.get_market_areas_df()["T_j"]
|
1995
1999
|
|
1996
2000
|
self.interaction_matrix.metadata["fit"] = {
|
1997
2001
|
"function": "huff_ml_fit",
|
@@ -2042,12 +2046,12 @@ class HuffModel:
|
|
2042
2046
|
|
2043
2047
|
except:
|
2044
2048
|
|
2045
|
-
print("Goodness-of-fit metrics could not be calculated due to NaN values.")
|
2049
|
+
print("WARNING: Goodness-of-fit metrics could not be calculated due to NaN values.")
|
2046
2050
|
return None
|
2047
2051
|
|
2048
2052
|
else:
|
2049
2053
|
|
2050
|
-
print("Goodness-of-fit metrics could not be calculated. No empirical values of probabilities in interaction matrix.")
|
2054
|
+
print("WARNING: Goodness-of-fit metrics could not be calculated. No empirical values of probabilities in interaction matrix.")
|
2051
2055
|
|
2052
2056
|
return None
|
2053
2057
|
|
@@ -2069,12 +2073,12 @@ class HuffModel:
|
|
2069
2073
|
|
2070
2074
|
except:
|
2071
2075
|
|
2072
|
-
print("Goodness-of-fit metrics could not be calculated due to NaN values.")
|
2076
|
+
print("WARNING: Goodness-of-fit metrics could not be calculated due to NaN values.")
|
2073
2077
|
return None
|
2074
2078
|
|
2075
2079
|
else:
|
2076
2080
|
|
2077
|
-
print("Goodness-of-fit metrics could not be calculated. No empirical values of customer flows in interaction matrix.")
|
2081
|
+
print("WARNING: Goodness-of-fit metrics could not be calculated. No empirical values of customer flows in interaction matrix.")
|
2078
2082
|
|
2079
2083
|
return None
|
2080
2084
|
|
@@ -2095,12 +2099,12 @@ class HuffModel:
|
|
2095
2099
|
|
2096
2100
|
except:
|
2097
2101
|
|
2098
|
-
print("Goodness-of-fit metrics could not be calculated due to NaN values.")
|
2102
|
+
print("WARNING: Goodness-of-fit metrics could not be calculated due to NaN values.")
|
2099
2103
|
return None
|
2100
2104
|
|
2101
2105
|
else:
|
2102
2106
|
|
2103
|
-
print("Goodness-of-fit metrics could not be calculated. No empirical values of T_j in market areas data.")
|
2107
|
+
print("WARNING: Goodness-of-fit metrics could not be calculated. No empirical values of T_j in market areas data.")
|
2104
2108
|
|
2105
2109
|
return None
|
2106
2110
|
|
@@ -2174,7 +2178,7 @@ class MCIModel:
|
|
2174
2178
|
|
2175
2179
|
except:
|
2176
2180
|
|
2177
|
-
print("Goodness-of-fit metrics could not be calculated due to NaN values.")
|
2181
|
+
print("WARNING: Goodness-of-fit metrics could not be calculated due to NaN values.")
|
2178
2182
|
return None
|
2179
2183
|
|
2180
2184
|
else:
|
@@ -2224,7 +2228,6 @@ class MCIModel:
|
|
2224
2228
|
print ("Goodness-of-fit for probabilities")
|
2225
2229
|
|
2226
2230
|
print("Sum of squared residuals ", round(mci_modelfit[1]["SQR"], 2))
|
2227
|
-
print("Sum of squares ", round(mci_modelfit[1]["SQT"], 2))
|
2228
2231
|
print("R-squared ", round(mci_modelfit[1]["Rsq"], 2))
|
2229
2232
|
print("Mean squared error ", round(mci_modelfit[1]["MSE"], 2))
|
2230
2233
|
print("Root mean squared error ", round(mci_modelfit[1]["RMSE"], 2))
|
@@ -3129,7 +3132,7 @@ def modelfit(
|
|
3129
3132
|
|
3130
3133
|
if len(obs_exp_clean) < len(observed) or len(obs_exp_clean) < len(expected):
|
3131
3134
|
if verbose:
|
3132
|
-
print("Vectors 'observed' and/or 'expected' contain zeros which are dropped.")
|
3135
|
+
print("NOTE: Vectors 'observed' and/or 'expected' contain zeros which are dropped.")
|
3133
3136
|
|
3134
3137
|
observed = obs_exp_clean["observed"].to_numpy()
|
3135
3138
|
expected = obs_exp_clean["expected"].to_numpy()
|
Binary file
|
@@ -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.
|
8
|
-
# Last update: 2025-07-
|
7
|
+
# Version: 1.5.2
|
8
|
+
# Last update: 2025-07-02 21:10
|
9
9
|
# Copyright (c) 2025 Thomas Wieland
|
10
10
|
#-----------------------------------------------------------------------
|
11
11
|
|
@@ -354,6 +354,9 @@ huff_model_fit3 = huff_model_fit2.ml_fit(
|
|
354
354
|
huff_model_fit3.summary()
|
355
355
|
# Show summary
|
356
356
|
|
357
|
+
print(huff_model_fit3.get_market_areas_df())
|
358
|
+
# Show market areas df
|
359
|
+
|
357
360
|
|
358
361
|
# Buffer analysis:
|
359
362
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: huff
|
3
|
-
Version: 1.5.
|
3
|
+
Version: 1.5.2
|
4
4
|
Summary: huff: Huff Model Market Area Analysis
|
5
5
|
Author: Thomas Wieland
|
6
6
|
Author-email: geowieland@googlemail.com
|
@@ -18,14 +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.
|
22
|
-
- Extensions:
|
23
|
-
- HuffModel.ml_fit(): Fit Huff model parameters by empirical total market areas
|
24
|
-
- HuffModel.summary(): Goodnes-of-fit depends on fit_by
|
25
|
-
- load_market_areas(): Loading table with totals and including into InteractionMatrix, HuffModel and MCIModel objects
|
21
|
+
## Updates v1.5.2
|
26
22
|
- Bugfixes:
|
27
|
-
-
|
28
|
-
-
|
23
|
+
- HuffModel.ml_fit(): Correct values of expected T_j, corrected calculation of model fit metrices when fit_by="totals"
|
24
|
+
- HuffModel.ml_fit(): Check if sum of E_ij != sum of T_j
|
29
25
|
|
30
26
|
|
31
27
|
## Features
|
@@ -34,7 +30,7 @@ See the /tests directory for usage examples of most of the included functions.
|
|
34
30
|
- Defining origins and destinations with weightings
|
35
31
|
- Creating interaction matrix from origins and destinations
|
36
32
|
- Different function types: power, exponential, logistic
|
37
|
-
- Huff model parameter estimation via Maximum Likelihood (ML) by probalities and
|
33
|
+
- Huff model parameter estimation via Maximum Likelihood (ML) by probalities, customer flows, and total market areas
|
38
34
|
- Huff model market simulation
|
39
35
|
- **Multiplicative Competitive Interaction Model**:
|
40
36
|
- Log-centering transformation of interaction matrix
|
Binary file
|
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
|
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
|