growthcharts 0.1.0__py3-none-any.whl → 0.2.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.
- growthcharts/child.py +320 -160
- growthcharts/infant.py +387 -193
- growthcharts/patient.py +37 -0
- {growthcharts-0.1.0.dist-info → growthcharts-0.2.0.dist-info}/METADATA +45 -19
- {growthcharts-0.1.0.dist-info → growthcharts-0.2.0.dist-info}/RECORD +8 -8
- {growthcharts-0.1.0.dist-info → growthcharts-0.2.0.dist-info}/WHEEL +0 -0
- {growthcharts-0.1.0.dist-info → growthcharts-0.2.0.dist-info}/licenses/LICENSE.txt +0 -0
- {growthcharts-0.1.0.dist-info → growthcharts-0.2.0.dist-info}/top_level.txt +0 -0
growthcharts/child.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
import matplotlib.pyplot as plt
|
|
3
3
|
import math
|
|
4
|
+
import json
|
|
4
5
|
from scipy.stats import norm
|
|
5
6
|
|
|
6
7
|
from .patient import Patient
|
|
@@ -49,221 +50,380 @@ class Child(Patient):
|
|
|
49
50
|
|
|
50
51
|
super().__init__(sex, age, wt, length)
|
|
51
52
|
|
|
52
|
-
def plot_wtage(self, title=None):
|
|
53
|
+
def plot_wtage(self, title=None, figsize=(12,7), show=True, ax=None):
|
|
53
54
|
"""
|
|
54
|
-
|
|
55
|
+
Plot weight-for-age growth chart for the child.
|
|
56
|
+
|
|
57
|
+
This method draws CDC percentile curves and overlays
|
|
58
|
+
the patient's weight measurement.
|
|
59
|
+
|
|
60
|
+
The returned figure can be customized, embedded in apps,
|
|
61
|
+
or saved as an image.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
title (str, optional):
|
|
65
|
+
Custom title for the chart.
|
|
66
|
+
|
|
67
|
+
figsize (tuple, optional):
|
|
68
|
+
Figure size in inches (width, height).
|
|
69
|
+
Default is (12, 7).
|
|
70
|
+
|
|
71
|
+
show (bool, optional):
|
|
72
|
+
Whether to display the plot using matplotlib.
|
|
73
|
+
If False, the plot will not be shown.
|
|
74
|
+
Default is True.
|
|
75
|
+
|
|
76
|
+
ax (matplotlib.axes.Axes, optional):
|
|
77
|
+
Existing matplotlib Axes object for embedding
|
|
78
|
+
in custom layouts or applications.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
tuple:
|
|
82
|
+
(fig, ax)
|
|
83
|
+
|
|
84
|
+
fig : matplotlib.figure.Figure
|
|
85
|
+
The created matplotlib figure.
|
|
86
|
+
|
|
87
|
+
ax : matplotlib.axes.Axes
|
|
88
|
+
The axes containing the plot.
|
|
89
|
+
"""
|
|
55
90
|
|
|
56
|
-
Args:
|
|
57
|
-
title (str, optional): Plot title.
|
|
58
|
-
"""
|
|
59
91
|
df = self.df_wtage
|
|
92
|
+
sex = self._normalize_sex()
|
|
60
93
|
|
|
61
|
-
|
|
62
|
-
if self.sex in ['m', '1']:
|
|
63
|
-
self.sex = '1'
|
|
64
|
-
elif self.sex in ['f', '2']:
|
|
65
|
-
self.sex = '2'
|
|
66
|
-
else:
|
|
67
|
-
raise TypeError('define sex as m or f')
|
|
94
|
+
data = df[df['Sex'] == sex]
|
|
68
95
|
|
|
69
|
-
|
|
96
|
+
if ax is None:
|
|
97
|
+
fig, ax = plt.subplots(figsize=figsize)
|
|
98
|
+
else:
|
|
99
|
+
fig = ax.figure
|
|
70
100
|
|
|
71
|
-
plt.figure(figsize=(12, 7))
|
|
72
101
|
for i, col in enumerate(self.agecolumns[1:]):
|
|
102
|
+
|
|
73
103
|
if i in self.highlight_indices:
|
|
74
|
-
|
|
75
|
-
|
|
104
|
+
ax.plot(
|
|
105
|
+
data['Agemos'], data[col],
|
|
106
|
+
color='gray', linewidth=2,
|
|
107
|
+
label=col
|
|
108
|
+
)
|
|
76
109
|
else:
|
|
77
|
-
|
|
78
|
-
|
|
110
|
+
ax.plot(
|
|
111
|
+
data['Agemos'], data[col],
|
|
112
|
+
color='lightgray', linewidth=1
|
|
113
|
+
)
|
|
79
114
|
|
|
80
115
|
if self.wt is not None:
|
|
81
|
-
|
|
116
|
+
ax.scatter(
|
|
117
|
+
self.age, self.wt,
|
|
118
|
+
color='red', s=100,
|
|
119
|
+
zorder=5, label="Patient"
|
|
120
|
+
)
|
|
82
121
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
plt.show()
|
|
122
|
+
ax.set_title(title or "Weight for Age")
|
|
123
|
+
ax.set_xlabel("Age (months)")
|
|
124
|
+
ax.set_ylabel("Weight (Kg)")
|
|
125
|
+
ax.grid(True)
|
|
126
|
+
ax.legend()
|
|
89
127
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
Plot length-for-age growth chart with patient's measurement.
|
|
128
|
+
if show:
|
|
129
|
+
plt.show()
|
|
93
130
|
|
|
94
|
-
|
|
95
|
-
|
|
131
|
+
return fig, ax
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def plot_lenage(self, title=None, figsize=(12,7), show=True, ax=None):
|
|
96
135
|
"""
|
|
136
|
+
Plot length/height-for-age growth chart for the child.
|
|
137
|
+
|
|
138
|
+
This method draws CDC percentile curves and overlays
|
|
139
|
+
the patient's length or height measurement.
|
|
140
|
+
|
|
141
|
+
The output figure can be customized, embedded in
|
|
142
|
+
applications, or exported as an image file.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
title (str, optional):
|
|
146
|
+
Custom title for the chart.
|
|
147
|
+
|
|
148
|
+
figsize (tuple, optional):
|
|
149
|
+
Figure size in inches (width, height).
|
|
150
|
+
Default is (12, 7).
|
|
151
|
+
|
|
152
|
+
show (bool, optional):
|
|
153
|
+
Whether to display the plot using matplotlib.
|
|
154
|
+
If False, the plot will not be shown.
|
|
155
|
+
Default is True.
|
|
156
|
+
|
|
157
|
+
ax (matplotlib.axes.Axes, optional):
|
|
158
|
+
Existing matplotlib Axes object for embedding
|
|
159
|
+
in custom layouts or applications.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
tuple:
|
|
163
|
+
(fig, ax)
|
|
164
|
+
|
|
165
|
+
fig : matplotlib.figure.Figure
|
|
166
|
+
The created matplotlib figure.
|
|
167
|
+
|
|
168
|
+
ax : matplotlib.axes.Axes
|
|
169
|
+
The axes containing the plot.
|
|
170
|
+
"""
|
|
171
|
+
|
|
97
172
|
df = self.df_lenage
|
|
173
|
+
sex = self._normalize_sex()
|
|
98
174
|
|
|
99
|
-
|
|
100
|
-
if self.sex in ['m', '1']:
|
|
101
|
-
self.sex = '1'
|
|
102
|
-
elif self.sex in ['f', '2']:
|
|
103
|
-
self.sex = '2'
|
|
104
|
-
else:
|
|
105
|
-
raise TypeError('define sex as m or f')
|
|
175
|
+
data = df[df['Sex'] == sex]
|
|
106
176
|
|
|
107
|
-
|
|
177
|
+
if ax is None:
|
|
178
|
+
fig, ax = plt.subplots(figsize=figsize)
|
|
179
|
+
else:
|
|
180
|
+
fig = ax.figure
|
|
108
181
|
|
|
109
|
-
plt.figure(figsize=(14, 10))
|
|
110
182
|
for i, col in enumerate(self.agecolumns[1:]):
|
|
183
|
+
|
|
111
184
|
if i in self.highlight_indices:
|
|
112
|
-
|
|
113
|
-
|
|
185
|
+
ax.plot(
|
|
186
|
+
data['Agemos'], data[col],
|
|
187
|
+
color='gray', linewidth=2,
|
|
188
|
+
label=col
|
|
189
|
+
)
|
|
114
190
|
else:
|
|
115
|
-
|
|
116
|
-
|
|
191
|
+
ax.plot(
|
|
192
|
+
data['Agemos'], data[col],
|
|
193
|
+
color='lightgray', linewidth=1
|
|
194
|
+
)
|
|
117
195
|
|
|
118
196
|
if self.length is not None:
|
|
119
|
-
|
|
197
|
+
ax.scatter(
|
|
198
|
+
self.age, self.length,
|
|
199
|
+
color='red', s=100,
|
|
200
|
+
zorder=5, label="Patient"
|
|
201
|
+
)
|
|
120
202
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
plt.show()
|
|
203
|
+
ax.set_title(title or "Length for Age")
|
|
204
|
+
ax.set_xlabel("Age (months)")
|
|
205
|
+
ax.set_ylabel("Length (cm)")
|
|
206
|
+
ax.grid(True)
|
|
207
|
+
ax.legend()
|
|
127
208
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
Plot BMI-for-age growth chart with patient's measurement.
|
|
209
|
+
if show:
|
|
210
|
+
plt.show()
|
|
131
211
|
|
|
132
|
-
|
|
133
|
-
|
|
212
|
+
return fig, ax
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def plot_bmiage(self, title=None, figsize=(12,7), show=True, ax=None):
|
|
134
216
|
"""
|
|
217
|
+
Plot BMI-for-age growth chart for the child.
|
|
218
|
+
|
|
219
|
+
This method draws CDC BMI percentile curves and overlays
|
|
220
|
+
the patient's calculated BMI value.
|
|
221
|
+
|
|
222
|
+
The resulting figure can be modified, embedded in apps,
|
|
223
|
+
or saved to disk.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
title (str, optional):
|
|
227
|
+
Custom title for the chart.
|
|
228
|
+
|
|
229
|
+
figsize (tuple, optional):
|
|
230
|
+
Figure size in inches (width, height).
|
|
231
|
+
Default is (12, 7).
|
|
232
|
+
|
|
233
|
+
show (bool, optional):
|
|
234
|
+
Whether to display the plot using matplotlib.
|
|
235
|
+
If False, the plot will not be shown.
|
|
236
|
+
Default is True.
|
|
237
|
+
|
|
238
|
+
ax (matplotlib.axes.Axes, optional):
|
|
239
|
+
Existing matplotlib Axes object for embedding
|
|
240
|
+
in custom layouts or applications.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
tuple:
|
|
244
|
+
(fig, ax)
|
|
245
|
+
|
|
246
|
+
fig : matplotlib.figure.Figure
|
|
247
|
+
The created matplotlib figure.
|
|
248
|
+
|
|
249
|
+
ax : matplotlib.axes.Axes
|
|
250
|
+
The axes containing the plot.
|
|
251
|
+
"""
|
|
252
|
+
|
|
135
253
|
df = self.df_bmiage
|
|
254
|
+
sex = self._normalize_sex()
|
|
136
255
|
|
|
137
|
-
|
|
138
|
-
if self.sex in ['m', '1']:
|
|
139
|
-
self.sex = '1'
|
|
140
|
-
elif self.sex in ['f', '2']:
|
|
141
|
-
self.sex = '2'
|
|
142
|
-
else:
|
|
143
|
-
raise TypeError('define sex as m or f')
|
|
256
|
+
data = df[df['Sex'] == sex]
|
|
144
257
|
|
|
145
|
-
|
|
258
|
+
if ax is None:
|
|
259
|
+
fig, ax = plt.subplots(figsize=figsize)
|
|
260
|
+
else:
|
|
261
|
+
fig = ax.figure
|
|
146
262
|
|
|
147
|
-
plt.figure(figsize=(12, 7))
|
|
148
263
|
for i, col in enumerate(self.agecolumns[1:]):
|
|
264
|
+
|
|
149
265
|
if i in self.highlight_indices:
|
|
150
|
-
|
|
151
|
-
|
|
266
|
+
ax.plot(
|
|
267
|
+
data['Agemos'], data[col],
|
|
268
|
+
color='gray', linewidth=2,
|
|
269
|
+
label=col
|
|
270
|
+
)
|
|
152
271
|
else:
|
|
153
|
-
|
|
154
|
-
|
|
272
|
+
ax.plot(
|
|
273
|
+
data['Agemos'], data[col],
|
|
274
|
+
color='lightgray', linewidth=1
|
|
275
|
+
)
|
|
155
276
|
|
|
156
|
-
if self.wt
|
|
157
|
-
|
|
277
|
+
if self.wt and self.length and self.length > 0:
|
|
278
|
+
ax.scatter(
|
|
279
|
+
self.age, self.bmi,
|
|
280
|
+
color='red', s=100,
|
|
281
|
+
zorder=5, label="Patient"
|
|
282
|
+
)
|
|
158
283
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
plt.show()
|
|
284
|
+
ax.set_title(title or "BMI for Age")
|
|
285
|
+
ax.set_xlabel("Age (months)")
|
|
286
|
+
ax.set_ylabel("BMI")
|
|
287
|
+
ax.grid(True)
|
|
288
|
+
ax.legend()
|
|
165
289
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
Analyze weight-for-age using LMS method.
|
|
290
|
+
if show:
|
|
291
|
+
plt.show()
|
|
169
292
|
|
|
170
|
-
|
|
171
|
-
dict: Z-score and percentile.
|
|
172
|
-
"""
|
|
173
|
-
df = self.df_wtage
|
|
174
|
-
self.sex = str(self.sex).lower()
|
|
175
|
-
if self.sex in ['m', '1']:
|
|
176
|
-
self.sex = '1'
|
|
177
|
-
elif self.sex in ['f', '2']:
|
|
178
|
-
self.sex = '2'
|
|
179
|
-
else:
|
|
180
|
-
raise TypeError('define sex as m or f')
|
|
293
|
+
return fig, ax
|
|
181
294
|
|
|
182
|
-
df2 = df[df['Sex'] == self.sex]
|
|
183
|
-
row = df2.iloc[(df2['Agemos'] - self.age).abs().argsort()[:1]]
|
|
184
295
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
296
|
+
def analyze_wtage(self, return_json=False):
|
|
297
|
+
"""
|
|
298
|
+
Analyze weight-for-age using LMS method.
|
|
188
299
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
else:
|
|
192
|
-
z = math.log(self.wt / M) / S
|
|
300
|
+
Args:
|
|
301
|
+
return_json (bool): If True, returns a JSON string. Default False.
|
|
193
302
|
|
|
194
|
-
|
|
303
|
+
Returns:
|
|
304
|
+
dict or JSON: Z-score, percentile, and interpretation.
|
|
305
|
+
"""
|
|
306
|
+
df = self.df_wtage
|
|
307
|
+
sex = self._normalize_sex()
|
|
308
|
+
df2 = df[df['Sex'] == sex]
|
|
195
309
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
"Percentile": round(percentile, 2)
|
|
199
|
-
}
|
|
310
|
+
row = df2.iloc[(df2['Agemos'] - self.age).abs().argsort()[:1]]
|
|
311
|
+
L, M, S = float(row['L'].values[0]), float(row['M'].values[0]), float(row['S'].values[0])
|
|
200
312
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
313
|
+
if L != 0:
|
|
314
|
+
z = ((self.wt / M) ** L - 1) / (L * S)
|
|
315
|
+
else:
|
|
316
|
+
z = math.log(self.wt / M) / S
|
|
204
317
|
|
|
205
|
-
|
|
206
|
-
dict: Z-score and percentile.
|
|
207
|
-
"""
|
|
208
|
-
df = self.df_lenage
|
|
209
|
-
self.sex = str(self.sex).lower()
|
|
210
|
-
if self.sex in ['m', '1']:
|
|
211
|
-
self.sex = '1'
|
|
212
|
-
elif self.sex in ['f', '2']:
|
|
213
|
-
self.sex = '2'
|
|
214
|
-
else:
|
|
215
|
-
raise TypeError('define sex as m or f')
|
|
318
|
+
percentile = norm.cdf(z) * 100
|
|
216
319
|
|
|
217
|
-
|
|
218
|
-
|
|
320
|
+
result = {
|
|
321
|
+
"indicator": "Weight-for-Age",
|
|
322
|
+
"value": round(self.wt, 2),
|
|
323
|
+
"unit": None,
|
|
324
|
+
"Age_Months": round(self.age, 2),
|
|
325
|
+
"sex": "Male" if sex == "1" else "Female",
|
|
219
326
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
S = float(row['S'].values[0])
|
|
327
|
+
"z_score": round(z, 2),
|
|
328
|
+
"percentile": round(percentile, 1),
|
|
223
329
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
z = math.log(self.length / M) / S
|
|
330
|
+
"z_interpretation": self._interpret_z(z),
|
|
331
|
+
"percentile_interpretation": self._interpret_percentile(percentile)
|
|
332
|
+
}
|
|
228
333
|
|
|
229
|
-
|
|
334
|
+
if return_json:
|
|
335
|
+
import json
|
|
336
|
+
return json.dumps(result)
|
|
230
337
|
|
|
231
|
-
|
|
232
|
-
"Z": round(z, 2),
|
|
233
|
-
"Percentile": round(percentile, 2)
|
|
234
|
-
}
|
|
338
|
+
return result
|
|
235
339
|
|
|
236
|
-
def analyze_bmiage(self):
|
|
237
|
-
"""
|
|
238
|
-
Analyze BMI-for-age using LMS method.
|
|
239
340
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
df = self.df_bmiage
|
|
244
|
-
self.sex = str(self.sex).lower()
|
|
245
|
-
if self.sex in ['m', '1']:
|
|
246
|
-
self.sex = '1'
|
|
247
|
-
elif self.sex in ['f', '2']:
|
|
248
|
-
self.sex = '2'
|
|
249
|
-
else:
|
|
250
|
-
raise TypeError('define sex as m or f')
|
|
341
|
+
def analyze_lenage(self, return_json=False):
|
|
342
|
+
"""
|
|
343
|
+
Analyze length-for-age using LMS method.
|
|
251
344
|
|
|
252
|
-
|
|
253
|
-
|
|
345
|
+
Args:
|
|
346
|
+
return_json (bool): If True, returns a JSON string. Default False.
|
|
254
347
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
348
|
+
Returns:
|
|
349
|
+
dict or JSON: Z-score, percentile, and interpretation.
|
|
350
|
+
"""
|
|
351
|
+
df = self.df_lenage
|
|
352
|
+
sex = self._normalize_sex()
|
|
353
|
+
df2 = df[df['Sex'] == sex]
|
|
258
354
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
355
|
+
row = df2.iloc[(df2['Agemos'] - self.age).abs().argsort()[:1]]
|
|
356
|
+
L, M, S = float(row['L'].values[0]), float(row['M'].values[0]), float(row['S'].values[0])
|
|
357
|
+
|
|
358
|
+
if L != 0:
|
|
359
|
+
z = ((self.length / M) ** L - 1) / (L * S)
|
|
360
|
+
else:
|
|
361
|
+
z = math.log(self.length / M) / S
|
|
362
|
+
|
|
363
|
+
percentile = norm.cdf(z) * 100
|
|
364
|
+
|
|
365
|
+
result = {
|
|
366
|
+
"indicator": "Length-for-Age",
|
|
367
|
+
"value": round(self.length, 2),
|
|
368
|
+
"unit": None,
|
|
369
|
+
"Age_Months": round(self.age, 2),
|
|
370
|
+
"sex": "Male" if sex == "1" else "Female",
|
|
371
|
+
|
|
372
|
+
"z_score": round(z, 2),
|
|
373
|
+
"percentile": round(percentile, 1),
|
|
374
|
+
|
|
375
|
+
"z_interpretation": self._interpret_z(z),
|
|
376
|
+
"percentile_interpretation": self._interpret_percentile(percentile)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if return_json:
|
|
380
|
+
import json
|
|
381
|
+
return json.dumps(result)
|
|
382
|
+
|
|
383
|
+
return result
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def analyze_bmiage(self, return_json=False):
|
|
387
|
+
"""
|
|
388
|
+
Analyze BMI-for-age using LMS method.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
return_json (bool): If True, returns a JSON string. Default False.
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
dict or JSON: Z-score, percentile, and interpretation.
|
|
395
|
+
"""
|
|
396
|
+
df = self.df_bmiage
|
|
397
|
+
sex = self._normalize_sex()
|
|
398
|
+
df2 = df[df['Sex'] == sex]
|
|
399
|
+
|
|
400
|
+
row = df2.iloc[(df2['Agemos'] - self.age).abs().argsort()[:1]]
|
|
401
|
+
L, M, S = float(row['L'].values[0]), float(row['M'].values[0]), float(row['S'].values[0])
|
|
402
|
+
|
|
403
|
+
if L != 0:
|
|
404
|
+
z = ((self.bmi / M) ** L - 1) / (L * S)
|
|
405
|
+
else:
|
|
406
|
+
z = math.log(self.bmi / M) / S
|
|
407
|
+
|
|
408
|
+
percentile = norm.cdf(z) * 100
|
|
409
|
+
|
|
410
|
+
result = {
|
|
411
|
+
"indicator": "BMI-for-Age",
|
|
412
|
+
"value": round(self.bmi, 2),
|
|
413
|
+
"unit": None,
|
|
414
|
+
"Age_Months": round(self.age, 2),
|
|
415
|
+
"sex": "Male" if sex == "1" else "Female",
|
|
416
|
+
|
|
417
|
+
"z_score": round(z, 2),
|
|
418
|
+
"percentile": round(percentile, 1),
|
|
419
|
+
|
|
420
|
+
"z_interpretation": self._interpret_z(z),
|
|
421
|
+
"percentile_interpretation": self._interpret_percentile(percentile)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if return_json:
|
|
425
|
+
import json
|
|
426
|
+
return json.dumps(result)
|
|
263
427
|
|
|
264
|
-
|
|
428
|
+
return result
|
|
265
429
|
|
|
266
|
-
return {
|
|
267
|
-
"Z": round(z, 2),
|
|
268
|
-
"Percentile": round(percentile, 2)
|
|
269
|
-
}
|