population-trend 3.0.0__py3-none-any.whl → 3.1.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.
- population_trend/__init__.py +3 -1
- population_trend/calculate_growth_rates.py +206 -0
- {population_trend-3.0.0.dist-info → population_trend-3.1.0.dist-info}/METADATA +2 -2
- population_trend-3.1.0.dist-info/RECORD +9 -0
- population_trend-3.0.0.dist-info/RECORD +0 -8
- {population_trend-3.0.0.dist-info → population_trend-3.1.0.dist-info}/LICENSE +0 -0
- {population_trend-3.0.0.dist-info → population_trend-3.1.0.dist-info}/WHEEL +0 -0
population_trend/__init__.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""A template Python module"""
|
|
2
2
|
|
|
3
|
-
__version__ = "3.
|
|
3
|
+
__version__ = "3.1.0"
|
|
4
4
|
from .cli import * # noqa
|
|
5
5
|
from .filter_data import * # noqa
|
|
6
6
|
from .population_growth_model import * # noqa
|
|
7
|
+
from .calculate_growth_rates import * # noqa
|
|
8
|
+
from bootstrapping_tools import * # noqa
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
from bootstrapping_tools import (
|
|
2
|
+
lambda_calculator,
|
|
3
|
+
power_law,
|
|
4
|
+
bootstrap_from_time_series,
|
|
5
|
+
get_bootstrap_deltas,
|
|
6
|
+
generate_latex_interval_string,
|
|
7
|
+
calculate_p_values,
|
|
8
|
+
)
|
|
9
|
+
from matplotlib.ticker import MaxNLocator
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
13
|
+
import numpy as np
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def do_nothing():
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def fit_population_model(seasons_series, data_series):
|
|
21
|
+
parameters = lambda_calculator(seasons_series, data_series)
|
|
22
|
+
model = power_law(
|
|
23
|
+
seasons_series - seasons_series.iloc[0],
|
|
24
|
+
parameters[0],
|
|
25
|
+
parameters[1],
|
|
26
|
+
)
|
|
27
|
+
return model
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def calculate_porcentual_diff(x, y):
|
|
31
|
+
return 100 * (x - y) / y
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def generate_number_and_season_string(number, season):
|
|
35
|
+
return "{} ({})".format(
|
|
36
|
+
number,
|
|
37
|
+
season,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def calculate_seasons_intervals(seasons):
|
|
42
|
+
years = []
|
|
43
|
+
first_index = 0
|
|
44
|
+
for index in np.where(np.diff(seasons) != 1)[0]:
|
|
45
|
+
if seasons[first_index] == seasons[index]:
|
|
46
|
+
years.append(f"{seasons[index]}")
|
|
47
|
+
else:
|
|
48
|
+
years.append(f"{seasons[first_index]}-{seasons[index]}")
|
|
49
|
+
first_index = index + 1
|
|
50
|
+
years.append(f"{seasons[first_index]}-{seasons[-1]}")
|
|
51
|
+
return years
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def calculate_interest_numbers(cantidad_nidos, model):
|
|
55
|
+
first_number = generate_number_and_season_string(
|
|
56
|
+
cantidad_nidos["Maxima_cantidad_nidos"].iloc[0],
|
|
57
|
+
cantidad_nidos["Temporada"].iloc[0],
|
|
58
|
+
)
|
|
59
|
+
first_number_calculated = generate_number_and_season_string(
|
|
60
|
+
model.iloc[0], cantidad_nidos["Temporada"].iloc[0]
|
|
61
|
+
)
|
|
62
|
+
last_number = "{{{:,.0f}}} ({})".format(
|
|
63
|
+
cantidad_nidos["Maxima_cantidad_nidos"].iloc[-1],
|
|
64
|
+
int(cantidad_nidos["Temporada"].iloc[-1]),
|
|
65
|
+
)
|
|
66
|
+
last_number_calculated = generate_number_and_season_string(
|
|
67
|
+
model.iloc[-1],
|
|
68
|
+
cantidad_nidos["Temporada"].iloc[-1],
|
|
69
|
+
)
|
|
70
|
+
return first_number, first_number_calculated, last_number, last_number_calculated
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def calculate_percent_diff_in_seasons(cantidad_nidos, model):
|
|
74
|
+
if cantidad_nidos["Maxima_cantidad_nidos"].iloc[0] == 0:
|
|
75
|
+
porcentaje_cambio = calculate_porcentual_diff(model.iloc[-1], model.iloc[0])
|
|
76
|
+
else:
|
|
77
|
+
porcentaje_cambio = calculate_porcentual_diff(
|
|
78
|
+
model.iloc[-1], cantidad_nidos["Maxima_cantidad_nidos"].iloc[0]
|
|
79
|
+
)
|
|
80
|
+
return porcentaje_cambio
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class Bootstrap_from_time_series_parameterizer:
|
|
84
|
+
def __init__(self, blocks_length=3, N=2000):
|
|
85
|
+
self.parameters = dict(
|
|
86
|
+
dataframe=None,
|
|
87
|
+
column_name="Maxima_cantidad_nidos",
|
|
88
|
+
N=N,
|
|
89
|
+
return_distribution=True,
|
|
90
|
+
blocks_length=blocks_length,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def set_data(self, data):
|
|
94
|
+
self.parameters["dataframe"] = data
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
Bootstrap = dict(
|
|
98
|
+
default=Bootstrap_from_time_series_parameterizer(),
|
|
99
|
+
testing=Bootstrap_from_time_series_parameterizer(blocks_length=2, N=100),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class Bootstrap_from_time_series:
|
|
104
|
+
def __init__(self, bootstrap_parametrizer):
|
|
105
|
+
self.parameters = bootstrap_parametrizer.parameters
|
|
106
|
+
self.lambdas_distribution, self.intervals = self._calculate_distribution_and_interval()
|
|
107
|
+
self.season_series = self.parameters["dataframe"]["Temporada"]
|
|
108
|
+
self.data_series = self.parameters["dataframe"][self.parameters["column_name"]]
|
|
109
|
+
self.lambdas = [interval[0] for interval in self.intervals]
|
|
110
|
+
|
|
111
|
+
def get_distribution(self):
|
|
112
|
+
return self.lambdas_distribution
|
|
113
|
+
|
|
114
|
+
def _calculate_distribution_and_interval(self):
|
|
115
|
+
lambdas_distribution, intervals = bootstrap_from_time_series(**self.parameters)
|
|
116
|
+
return lambdas_distribution, intervals
|
|
117
|
+
|
|
118
|
+
def get_inferior_central_and_superior_limit(self):
|
|
119
|
+
inferior_limit, central, superior_limit = get_bootstrap_deltas(
|
|
120
|
+
self.lambdas, **{"decimals": 2}
|
|
121
|
+
)
|
|
122
|
+
return inferior_limit, central, superior_limit
|
|
123
|
+
|
|
124
|
+
def get_lambda_interval_latex_string(self):
|
|
125
|
+
lambda_latex_string = generate_latex_interval_string(self.lambdas, **{"decimals": 2})
|
|
126
|
+
return lambda_latex_string
|
|
127
|
+
|
|
128
|
+
def generate_season_interval(self):
|
|
129
|
+
return "({}-{})".format(
|
|
130
|
+
self.season_series.min(axis=0),
|
|
131
|
+
self.season_series.max(axis=0),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def get_monitored_seasons(self):
|
|
135
|
+
monitored_seasons = np.sort(self.season_series.astype(int).unique())
|
|
136
|
+
if len(monitored_seasons) == 1:
|
|
137
|
+
return f"{monitored_seasons[0]}"
|
|
138
|
+
else:
|
|
139
|
+
seasons_intervals = calculate_seasons_intervals(monitored_seasons)
|
|
140
|
+
return ",".join(seasons_intervals)
|
|
141
|
+
|
|
142
|
+
def xxfit_population_model(self):
|
|
143
|
+
parameters = lambda_calculator(self.season_series, self.data_series)
|
|
144
|
+
model = power_law(
|
|
145
|
+
self.season_series - self.season_series.iloc[0],
|
|
146
|
+
parameters[0],
|
|
147
|
+
parameters[1],
|
|
148
|
+
)
|
|
149
|
+
return model
|
|
150
|
+
|
|
151
|
+
def save_intervals(self, output_path):
|
|
152
|
+
json_dict = {
|
|
153
|
+
"intervals": list(self.intervals),
|
|
154
|
+
"lambda_latex_interval": self.get_lambda_interval_latex_string(),
|
|
155
|
+
}
|
|
156
|
+
with open(output_path, "w") as file:
|
|
157
|
+
json.dump(json_dict, file)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def calculate_growth_rates_table(bootstrap: Bootstrap_from_time_series_parameterizer):
|
|
161
|
+
bootstraper = Bootstrap_from_time_series(bootstrap)
|
|
162
|
+
df = bootstrap.parameters["dataframe"]
|
|
163
|
+
model = bootstraper.xxfit_population_model()
|
|
164
|
+
inferior_limit, central, superior_limit = bootstraper.get_inferior_central_and_superior_limit()
|
|
165
|
+
lambda_latex_string = bootstraper.get_lambda_interval_latex_string()
|
|
166
|
+
bootstrap_distribution = bootstraper.get_distribution()
|
|
167
|
+
lambdas_distribution = [interval[0] for interval in bootstrap_distribution]
|
|
168
|
+
p_value_mayor, p_value_menor = calculate_p_values(lambdas_distribution)
|
|
169
|
+
intervalo = bootstraper.generate_season_interval()
|
|
170
|
+
monitored_seasons = bootstraper.get_monitored_seasons()
|
|
171
|
+
porcentaje_cambio = calculate_percent_diff_in_seasons(df, model)
|
|
172
|
+
(
|
|
173
|
+
first_number,
|
|
174
|
+
_,
|
|
175
|
+
last_number,
|
|
176
|
+
last_number_calculated,
|
|
177
|
+
) = calculate_interest_numbers(df, model)
|
|
178
|
+
return [
|
|
179
|
+
intervalo,
|
|
180
|
+
first_number,
|
|
181
|
+
last_number,
|
|
182
|
+
last_number_calculated,
|
|
183
|
+
lambda_latex_string,
|
|
184
|
+
df["Latitud"].iloc[0],
|
|
185
|
+
central,
|
|
186
|
+
f"-{inferior_limit}",
|
|
187
|
+
f"+{superior_limit}",
|
|
188
|
+
f"{{{int(porcentaje_cambio):,}}}",
|
|
189
|
+
p_value_mayor,
|
|
190
|
+
p_value_menor,
|
|
191
|
+
monitored_seasons,
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def set_axis_plot_config(ax):
|
|
196
|
+
ax.xaxis.set_major_locator(MaxNLocator(integer=True))
|
|
197
|
+
ax.spines["right"].set_visible(False)
|
|
198
|
+
ax.spines["top"].set_visible(False)
|
|
199
|
+
plt.yticks(rotation=90, size=20)
|
|
200
|
+
locs_x, labels_x = plt.xticks()
|
|
201
|
+
locs_y, labels_y = plt.yticks()
|
|
202
|
+
plt.xticks(locs_x[1:], size=20)
|
|
203
|
+
plt.xlim(locs_x[0], locs_x[-1])
|
|
204
|
+
plt.ylim(0, locs_y[-1])
|
|
205
|
+
plt.xlabel("Año", size=20, labelpad=10)
|
|
206
|
+
plt.ylabel("Cantidad de parejas reproductoras", size=20)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: population_trend
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: A template Python module
|
|
5
5
|
Home-page: https://github.com/IslasGECI/population_trend
|
|
6
6
|
Author: Ciencia de Datos • GECI
|
|
@@ -8,7 +8,7 @@ Author-email: ciencia.datos@islas.org.mx
|
|
|
8
8
|
Requires-Python: >=3.9
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
11
|
-
Requires-Dist: bootstrapping-tools==
|
|
11
|
+
Requires-Dist: bootstrapping-tools==2.0.0
|
|
12
12
|
Requires-Dist: geci-plots
|
|
13
13
|
Requires-Dist: typer
|
|
14
14
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
population_trend/__init__.py,sha256=mr5F6CLyrEM5ITNVsP0YgFZff-b2E7GRbunCPuELGiA,251
|
|
2
|
+
population_trend/calculate_growth_rates.py,sha256=SQobh1f2xKFKu7MO7To7avxU2Cym1ebu2tKfpbLTpbo,6901
|
|
3
|
+
population_trend/cli.py,sha256=CkzXmfjekIV4RplUyJo1Af-GI22zovB4u5alt8BNYIo,1894
|
|
4
|
+
population_trend/filter_data.py,sha256=D0Y1vztcbbo98af9q7wRhlHfH__bNFI8tnVOdJY6hu0,403
|
|
5
|
+
population_trend/population_growth_model.py,sha256=fSUKg8UH-pdN1tNYskGcMmmiqqAy9Ciz0E4X-IeP9WM,4361
|
|
6
|
+
population_trend-3.1.0.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
7
|
+
population_trend-3.1.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
8
|
+
population_trend-3.1.0.dist-info/METADATA,sha256=e5YM8iZ6yCz3b9uRIrFOa2AeXa6uIPQ4bW77D0NAPno,1504
|
|
9
|
+
population_trend-3.1.0.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
population_trend/__init__.py,sha256=FT9rFbM8pRxixs5itfeXniGnSsbiZtuZ7bu_Ar8LEpI,163
|
|
2
|
-
population_trend/cli.py,sha256=CkzXmfjekIV4RplUyJo1Af-GI22zovB4u5alt8BNYIo,1894
|
|
3
|
-
population_trend/filter_data.py,sha256=D0Y1vztcbbo98af9q7wRhlHfH__bNFI8tnVOdJY6hu0,403
|
|
4
|
-
population_trend/population_growth_model.py,sha256=fSUKg8UH-pdN1tNYskGcMmmiqqAy9Ciz0E4X-IeP9WM,4361
|
|
5
|
-
population_trend-3.0.0.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
6
|
-
population_trend-3.0.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
7
|
-
population_trend-3.0.0.dist-info/METADATA,sha256=9DcQkh2bjrLU5e03CBPSBo970FgoSn9Na26OATSlKYk,1504
|
|
8
|
-
population_trend-3.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|