Update app.py
Browse files
app.py
CHANGED
@@ -33,29 +33,34 @@ def generar_tabla(n_filas, concentracion_inicial, unidad_medida):
|
|
33 |
|
34 |
nombre_columna = f"Soluci贸n de in贸culo ({concentracion_inicial} {unidad_medida})"
|
35 |
df["Factor de Diluci贸n"] = df[nombre_columna].apply(lambda x: round(1 / x, 2))
|
36 |
-
df[
|
37 |
-
lambda x:
|
38 |
)
|
39 |
-
|
40 |
df[f"Concentraci贸n Real ({unidad_medida})"] = None
|
41 |
|
42 |
return df
|
43 |
|
44 |
def ajustar_decimales_evento(df, decimales):
|
45 |
df = df.copy()
|
46 |
-
# Identificar la columna de Concentraci贸n Predicha
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
#
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
def generar_datos_sinteticos(df, desviacion_std):
|
54 |
-
|
55 |
col_real = [col for col in df.columns if 'Real' in col][0]
|
56 |
|
57 |
# Generar datos sint茅ticos
|
58 |
-
valores_predichos = df[
|
59 |
datos_sinteticos = valores_predichos + np.random.normal(0, desviacion_std, size=len(valores_predichos))
|
60 |
datos_sinteticos = np.maximum(0, datos_sinteticos) # Asegurar que no haya valores negativos
|
61 |
datos_sinteticos = np.round(datos_sinteticos, 2)
|
@@ -65,16 +70,16 @@ def generar_datos_sinteticos(df, desviacion_std):
|
|
65 |
return df
|
66 |
|
67 |
def generar_graficos(df_valid):
|
68 |
-
|
69 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
70 |
|
71 |
# Convertir a num茅rico
|
72 |
-
df_valid[
|
73 |
df_valid[col_real] = df_valid[col_real].astype(float)
|
74 |
|
75 |
# Calcular regresi贸n lineal
|
76 |
-
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[
|
77 |
-
df_valid['Ajuste Lineal'] = intercept + slope * df_valid[
|
78 |
|
79 |
# Configurar estilos
|
80 |
sns.set(style="whitegrid")
|
@@ -85,7 +90,7 @@ def generar_graficos(df_valid):
|
|
85 |
# Gr谩fico de dispersi贸n con l铆nea de regresi贸n
|
86 |
sns.scatterplot(
|
87 |
data=df_valid,
|
88 |
-
x=
|
89 |
y=col_real,
|
90 |
ax=ax1,
|
91 |
color='blue',
|
@@ -96,7 +101,7 @@ def generar_graficos(df_valid):
|
|
96 |
|
97 |
# L铆nea de ajuste
|
98 |
sns.lineplot(
|
99 |
-
x=df_valid[
|
100 |
y=df_valid['Ajuste Lineal'],
|
101 |
ax=ax1,
|
102 |
color='green',
|
@@ -105,8 +110,8 @@ def generar_graficos(df_valid):
|
|
105 |
)
|
106 |
|
107 |
# L铆nea ideal
|
108 |
-
min_predicha = df_valid[
|
109 |
-
max_predicha = df_valid[
|
110 |
ax1.plot(
|
111 |
[min_predicha, max_predicha],
|
112 |
[min_predicha, max_predicha],
|
@@ -136,7 +141,7 @@ def generar_graficos(df_valid):
|
|
136 |
residuos = df_valid[col_real] - df_valid['Ajuste Lineal']
|
137 |
sns.scatterplot(
|
138 |
data=df_valid,
|
139 |
-
x=
|
140 |
y=residuos,
|
141 |
ax=ax2,
|
142 |
color='purple',
|
@@ -185,17 +190,17 @@ def evaluar_calidad_calibracion(df_valid, r_squared, rmse, cv_percent):
|
|
185 |
|
186 |
def generar_informe_completo(df_valid):
|
187 |
"""Generar un informe completo en formato markdown"""
|
188 |
-
|
189 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
190 |
|
191 |
# Convertir a num茅rico
|
192 |
-
df_valid[
|
193 |
df_valid[col_real] = df_valid[col_real].astype(float)
|
194 |
|
195 |
# Calcular estad铆sticas
|
196 |
-
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[
|
197 |
r_squared = r_value ** 2
|
198 |
-
rmse = np.sqrt(((df_valid[col_real] - (intercept + slope * df_valid[
|
199 |
cv = (df_valid[col_real].std() / df_valid[col_real].mean()) * 100 # CV de los valores reales
|
200 |
|
201 |
# Evaluar calidad
|
@@ -231,21 +236,21 @@ def actualizar_analisis(df):
|
|
231 |
if df is None or df.empty:
|
232 |
return "Error en los datos", None, "No se pueden generar an谩lisis"
|
233 |
|
234 |
-
|
235 |
col_real = [col for col in df.columns if 'Real' in col][0]
|
236 |
|
237 |
# Convertir columnas a num茅rico
|
238 |
-
df[
|
239 |
df[col_real] = pd.to_numeric(df[col_real], errors='coerce')
|
240 |
|
241 |
-
df_valid = df.dropna(subset=[
|
242 |
|
243 |
if len(df_valid) < 2:
|
244 |
return "Se necesitan m谩s datos", None, "Se requieren al menos dos valores reales para el an谩lisis"
|
245 |
|
246 |
# Calcular la regresi贸n y agregar 'Ajuste Lineal'
|
247 |
-
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[
|
248 |
-
df_valid['Ajuste Lineal'] = intercept + slope * df_valid[
|
249 |
|
250 |
fig = generar_graficos(df_valid)
|
251 |
informe, estado = generar_informe_completo(df_valid)
|
@@ -345,14 +350,14 @@ def exportar_informe_latex(df_valid, informe_md):
|
|
345 |
|
346 |
def exportar_word(df, informe_md):
|
347 |
df_valid = df.copy()
|
348 |
-
|
349 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
350 |
|
351 |
# Convertir columnas a num茅rico
|
352 |
-
df_valid[
|
353 |
df_valid[col_real] = pd.to_numeric(df_valid[col_real], errors='coerce')
|
354 |
|
355 |
-
df_valid = df_valid.dropna(subset=[
|
356 |
|
357 |
if df_valid.empty:
|
358 |
return None
|
@@ -363,14 +368,14 @@ def exportar_word(df, informe_md):
|
|
363 |
|
364 |
def exportar_latex(df, informe_md):
|
365 |
df_valid = df.copy()
|
366 |
-
|
367 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
368 |
|
369 |
# Convertir columnas a num茅rico
|
370 |
-
df_valid[
|
371 |
df_valid[col_real] = pd.to_numeric(df_valid[col_real], errors='coerce')
|
372 |
|
373 |
-
df_valid = df_valid.dropna(subset=[
|
374 |
|
375 |
if df_valid.empty:
|
376 |
return None
|
@@ -406,9 +411,9 @@ def limpiar_datos():
|
|
406 |
|
407 |
def generar_datos_sinteticos_evento(df):
|
408 |
df = df.copy()
|
409 |
-
|
410 |
-
df[
|
411 |
-
desviacion_std = 0.05 * df[
|
412 |
df = generar_datos_sinteticos(df, desviacion_std)
|
413 |
return df
|
414 |
|
@@ -417,8 +422,6 @@ def actualizar_tabla_evento(df, n_filas, concentracion, unidad):
|
|
417 |
df_new = generar_tabla(n_filas, concentracion, unidad)
|
418 |
|
419 |
# Mapear columnas
|
420 |
-
col_predicha_new = [col for col in df_new.columns if 'Concentraci贸n Predicha' in col][0]
|
421 |
-
col_predicha_old = [col for col in df.columns if 'Concentraci贸n Predicha' in col][0]
|
422 |
col_real_new = [col for col in df_new.columns if 'Concentraci贸n Real' in col][0]
|
423 |
col_real_old = [col for col in df.columns if 'Concentraci贸n Real' in col][0]
|
424 |
|
@@ -476,13 +479,12 @@ with gr.Blocks(theme=gr.themes.Soft()) as interfaz:
|
|
476 |
|
477 |
tabla_output = gr.DataFrame(
|
478 |
row_count=(1, "dynamic"),
|
479 |
-
col_count=(
|
480 |
wrap=True,
|
481 |
label="Tabla de Datos",
|
482 |
interactive=True,
|
483 |
-
datatype=["number", "number", "number", "number", "number"],
|
484 |
type="pandas",
|
485 |
-
precision=0 # Establecer precisi贸n inicial
|
486 |
)
|
487 |
|
488 |
with gr.Tab("馃搳 An谩lisis y Reporte"):
|
|
|
33 |
|
34 |
nombre_columna = f"Soluci贸n de in贸culo ({concentracion_inicial} {unidad_medida})"
|
35 |
df["Factor de Diluci贸n"] = df[nombre_columna].apply(lambda x: round(1 / x, 2))
|
36 |
+
df["Concentraci贸n Predicha Num茅rica"] = df["Factor de Diluci贸n"].apply(
|
37 |
+
lambda x: concentracion_inicial / x
|
38 |
)
|
39 |
+
df[f"Concentraci贸n Predicha ({unidad_medida})"] = df["Concentraci贸n Predicha Num茅rica"].round(0).astype(str)
|
40 |
df[f"Concentraci贸n Real ({unidad_medida})"] = None
|
41 |
|
42 |
return df
|
43 |
|
44 |
def ajustar_decimales_evento(df, decimales):
|
45 |
df = df.copy()
|
46 |
+
# Identificar la columna de Concentraci贸n Predicha Num茅rica y la de visualizaci贸n
|
47 |
+
col_predicha_num = "Concentraci贸n Predicha Num茅rica"
|
48 |
+
col_predicha = [col for col in df.columns if 'Concentraci贸n Predicha (' in col][0]
|
49 |
+
|
50 |
+
# Redondear la columna num茅rica al n煤mero de decimales especificado
|
51 |
+
df[col_predicha_num] = df[col_predicha_num].astype(float).round(decimales)
|
52 |
+
|
53 |
+
# Actualizar la columna de visualizaci贸n con el formato deseado
|
54 |
+
df[col_predicha] = df[col_predicha_num].apply(lambda x: f"{x:.{decimales}f}")
|
55 |
+
|
56 |
+
return df
|
57 |
|
58 |
def generar_datos_sinteticos(df, desviacion_std):
|
59 |
+
col_predicha_num = "Concentraci贸n Predicha Num茅rica"
|
60 |
col_real = [col for col in df.columns if 'Real' in col][0]
|
61 |
|
62 |
# Generar datos sint茅ticos
|
63 |
+
valores_predichos = df[col_predicha_num].astype(float).values
|
64 |
datos_sinteticos = valores_predichos + np.random.normal(0, desviacion_std, size=len(valores_predichos))
|
65 |
datos_sinteticos = np.maximum(0, datos_sinteticos) # Asegurar que no haya valores negativos
|
66 |
datos_sinteticos = np.round(datos_sinteticos, 2)
|
|
|
70 |
return df
|
71 |
|
72 |
def generar_graficos(df_valid):
|
73 |
+
col_predicha_num = "Concentraci贸n Predicha Num茅rica"
|
74 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
75 |
|
76 |
# Convertir a num茅rico
|
77 |
+
df_valid[col_predicha_num] = df_valid[col_predicha_num].astype(float)
|
78 |
df_valid[col_real] = df_valid[col_real].astype(float)
|
79 |
|
80 |
# Calcular regresi贸n lineal
|
81 |
+
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[col_predicha_num], df_valid[col_real])
|
82 |
+
df_valid['Ajuste Lineal'] = intercept + slope * df_valid[col_predicha_num]
|
83 |
|
84 |
# Configurar estilos
|
85 |
sns.set(style="whitegrid")
|
|
|
90 |
# Gr谩fico de dispersi贸n con l铆nea de regresi贸n
|
91 |
sns.scatterplot(
|
92 |
data=df_valid,
|
93 |
+
x=col_predicha_num,
|
94 |
y=col_real,
|
95 |
ax=ax1,
|
96 |
color='blue',
|
|
|
101 |
|
102 |
# L铆nea de ajuste
|
103 |
sns.lineplot(
|
104 |
+
x=df_valid[col_predicha_num],
|
105 |
y=df_valid['Ajuste Lineal'],
|
106 |
ax=ax1,
|
107 |
color='green',
|
|
|
110 |
)
|
111 |
|
112 |
# L铆nea ideal
|
113 |
+
min_predicha = df_valid[col_predicha_num].min()
|
114 |
+
max_predicha = df_valid[col_predicha_num].max()
|
115 |
ax1.plot(
|
116 |
[min_predicha, max_predicha],
|
117 |
[min_predicha, max_predicha],
|
|
|
141 |
residuos = df_valid[col_real] - df_valid['Ajuste Lineal']
|
142 |
sns.scatterplot(
|
143 |
data=df_valid,
|
144 |
+
x=col_predicha_num,
|
145 |
y=residuos,
|
146 |
ax=ax2,
|
147 |
color='purple',
|
|
|
190 |
|
191 |
def generar_informe_completo(df_valid):
|
192 |
"""Generar un informe completo en formato markdown"""
|
193 |
+
col_predicha_num = "Concentraci贸n Predicha Num茅rica"
|
194 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
195 |
|
196 |
# Convertir a num茅rico
|
197 |
+
df_valid[col_predicha_num] = df_valid[col_predicha_num].astype(float)
|
198 |
df_valid[col_real] = df_valid[col_real].astype(float)
|
199 |
|
200 |
# Calcular estad铆sticas
|
201 |
+
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[col_predicha_num], df_valid[col_real])
|
202 |
r_squared = r_value ** 2
|
203 |
+
rmse = np.sqrt(((df_valid[col_real] - (intercept + slope * df_valid[col_predicha_num])) ** 2).mean())
|
204 |
cv = (df_valid[col_real].std() / df_valid[col_real].mean()) * 100 # CV de los valores reales
|
205 |
|
206 |
# Evaluar calidad
|
|
|
236 |
if df is None or df.empty:
|
237 |
return "Error en los datos", None, "No se pueden generar an谩lisis"
|
238 |
|
239 |
+
col_predicha_num = "Concentraci贸n Predicha Num茅rica"
|
240 |
col_real = [col for col in df.columns if 'Real' in col][0]
|
241 |
|
242 |
# Convertir columnas a num茅rico
|
243 |
+
df[col_predicha_num] = pd.to_numeric(df[col_predicha_num], errors='coerce')
|
244 |
df[col_real] = pd.to_numeric(df[col_real], errors='coerce')
|
245 |
|
246 |
+
df_valid = df.dropna(subset=[col_predicha_num, col_real])
|
247 |
|
248 |
if len(df_valid) < 2:
|
249 |
return "Se necesitan m谩s datos", None, "Se requieren al menos dos valores reales para el an谩lisis"
|
250 |
|
251 |
# Calcular la regresi贸n y agregar 'Ajuste Lineal'
|
252 |
+
slope, intercept, r_value, p_value, std_err = stats.linregress(df_valid[col_predicha_num], df_valid[col_real])
|
253 |
+
df_valid['Ajuste Lineal'] = intercept + slope * df_valid[col_predicha_num]
|
254 |
|
255 |
fig = generar_graficos(df_valid)
|
256 |
informe, estado = generar_informe_completo(df_valid)
|
|
|
350 |
|
351 |
def exportar_word(df, informe_md):
|
352 |
df_valid = df.copy()
|
353 |
+
col_predicha_num = "Concentraci贸n Predicha Num茅rica"
|
354 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
355 |
|
356 |
# Convertir columnas a num茅rico
|
357 |
+
df_valid[col_predicha_num] = pd.to_numeric(df_valid[col_predicha_num], errors='coerce')
|
358 |
df_valid[col_real] = pd.to_numeric(df_valid[col_real], errors='coerce')
|
359 |
|
360 |
+
df_valid = df_valid.dropna(subset=[col_predicha_num, col_real])
|
361 |
|
362 |
if df_valid.empty:
|
363 |
return None
|
|
|
368 |
|
369 |
def exportar_latex(df, informe_md):
|
370 |
df_valid = df.copy()
|
371 |
+
col_predicha_num = "Concentraci贸n Predicha Num茅rica"
|
372 |
col_real = [col for col in df_valid.columns if 'Real' in col][0]
|
373 |
|
374 |
# Convertir columnas a num茅rico
|
375 |
+
df_valid[col_predicha_num] = pd.to_numeric(df_valid[col_predicha_num], errors='coerce')
|
376 |
df_valid[col_real] = pd.to_numeric(df_valid[col_real], errors='coerce')
|
377 |
|
378 |
+
df_valid = df_valid.dropna(subset=[col_predicha_num, col_real])
|
379 |
|
380 |
if df_valid.empty:
|
381 |
return None
|
|
|
411 |
|
412 |
def generar_datos_sinteticos_evento(df):
|
413 |
df = df.copy()
|
414 |
+
col_predicha_num = "Concentraci贸n Predicha Num茅rica"
|
415 |
+
df[col_predicha_num] = pd.to_numeric(df[col_predicha_num], errors='coerce')
|
416 |
+
desviacion_std = 0.05 * df[col_predicha_num].mean() # 5% de la media como desviaci贸n est谩ndar
|
417 |
df = generar_datos_sinteticos(df, desviacion_std)
|
418 |
return df
|
419 |
|
|
|
422 |
df_new = generar_tabla(n_filas, concentracion, unidad)
|
423 |
|
424 |
# Mapear columnas
|
|
|
|
|
425 |
col_real_new = [col for col in df_new.columns if 'Concentraci贸n Real' in col][0]
|
426 |
col_real_old = [col for col in df.columns if 'Concentraci贸n Real' in col][0]
|
427 |
|
|
|
479 |
|
480 |
tabla_output = gr.DataFrame(
|
481 |
row_count=(1, "dynamic"),
|
482 |
+
col_count=(6, "fixed"),
|
483 |
wrap=True,
|
484 |
label="Tabla de Datos",
|
485 |
interactive=True,
|
486 |
+
datatype=["number", "number", "number", "number", "str", "number"],
|
487 |
type="pandas",
|
|
|
488 |
)
|
489 |
|
490 |
with gr.Tab("馃搳 An谩lisis y Reporte"):
|