import time import streamlit as st import pandas as pd import altair as alt import matplotlib.pyplot as plt st.markdown("""
""", unsafe_allow_html=True) st.write('__INVESTIGACIÓN EN ENTORNOS DIGITALES, DATA Y ANALÍTICA__') st.title('Mi primera predicción') ''' 👋 ¡Hola! Bienvenid@ a esta introducción a la __predicción de datos__. Con esta aplicación web podrás subir un archivo con __ejemplos__ de los que quieres aprender, realizar un breve __análisis exploratorio__ de variables y entrenar un modelo de __predicción__ sencillo. ''' #---------------------------------------- # Cargar datos #---------------------------------------- st.header('Carga de datos') file = st.file_uploader("Archivo CSV", type=["csv"]) if file is None : st.info('Para empezar, sube un archivo en __formato CSV__. Asegúrate de que el archivo no sea demasiado grande (menos de 2 MB) y que contenga una variable objetivo que quieras predecir.', icon=":material/north:") st.stop() # st.write("XSRF:", st.get_option("server.enableXsrfProtection")) st.success(f"Archivo __{file.name}__ subido con éxito (también se han limpiado los datos inválidos)", icon=":material/check:") df = pd.read_csv(file) df = df.dropna() num_rows, num_cols = df.shape num_numeric_cols = df.select_dtypes(include='number').shape[1] num_categorial_cols = df.columns.size - num_numeric_cols col1, col2, col3, col4 = st.columns(4) col1.container(border=True).metric("Ejemplos", f"{num_rows}") col2.container(border=True).metric("Variables", f"{num_cols}") col3.container(border=True).metric("Variables numéricas", f"{num_numeric_cols}") col4.container(border=True).metric("Variables categóricas", f"{num_categorial_cols}") with st.expander('Ver cómo son los datos (50 primeros)') : st.dataframe(df.head(50)) #---------------------------------------- # Seleccionar variable objetivo #---------------------------------------- st.header('Variable objetivo') target = st.selectbox("Variable objetivo", df.columns, index=None) if target is None: st.info('El siguiente paso es seleccionar la variable que queremos predecir a partir de las demás, que se denomina __variable objetivo__. Elige una del desplegable.', icon=":material/north:") st.stop() is_numeric = pd.api.types.is_numeric_dtype(df[target]) if is_numeric : st.success(f"Has seleccionado _{target}_, que es una variable __numérica__", icon=':material/check:') else: st.success(f"Has seleccionado _{target}_, que es una variable __categórica__", icon=':material/check:') st.caption(f'Distribución de la variable objetivo __{target}__') if is_numeric : chart = alt.Chart(df).mark_bar().encode( x=alt.X(f'{target}:Q', bin=alt.Bin(maxbins=30)), y='count()', ).properties( height=300 ) st.altair_chart(chart, width='stretch') else: chart = alt.Chart(df).mark_bar().encode( x=alt.X(f'{target}:N', sort='-y').axis(labelAngle=0), y='count()', ).properties( height=300 ) st.altair_chart(chart, width='stretch') #---------------------------------------- # Preprocesamiento #---------------------------------------- X_raw = df.drop(columns=[target]) y = df[target] X = pd.get_dummies(X_raw, drop_first=True) st.success(f'Se han eliminado __valores inválidos__ (sin valor) y se han convertido el resto de variables en __variables numéricas__ (importante para poder aprender y hacer predicciones)', icon=":material/check:") with st.expander('Ver como han quedado los datos (50 primeros)') : st.dataframe(X.head(50)) #---------------------------------------- # Análisis exploratorio #---------------------------------------- st.header('Análisis exploratorio') f''' Abajo tienes la lista de variables y su relación con la variable objetivo _{target}_. Cuanto más alto el valor, más afecta la variable a la variable objetivo _{target}_. ''' if is_numeric : from sklearn.feature_selection import mutual_info_regression scores = mutual_info_regression(X, y, random_state=42) else : from sklearn.feature_selection import mutual_info_classif scores = mutual_info_classif(X, y, random_state=42) df_features = pd.DataFrame({ 'Variable': X.columns, 'Importancia': scores, }).sort_values('Importancia', ascending=False) st.dataframe( df_features, column_config={ # 'Importancia': st.column_config.ProgressColumn('Importancia', min_value=0, max_value=df_features['Importancia'].max()), 'Importancia': st.column_config.ProgressColumn('Importancia', min_value=0, max_value=df_features['Importancia'].max(), format='%.2f'), }, use_container_width=True ) st.caption(':material/info: La primera barra siempre aparece llena, se pone a modo de comparación') selected = st.multiselect('Variables para el entrenamiento', options=X.columns, ) if len(selected) == 0 : st.info('Tras los resultados del análisis exploratorio, elige qué __variables__ utilizarás para el __entrenamiento__ del modelo. Cuantas más pongas, menos eficiente será, y poner más variables no es sinónimo de mejores resultados (pero normalmente ayuda).', icon=":material/north:") st.stop() X_selected = X[selected] st.success(f'Has elegido __{len(selected)} {"variables" if len(selected) > 1 else "variable"}__ para el entrenamiento (las demás se han eliminado)', icon=":material/check:") with st.expander('Ver como han quedado los datos (50 primeros)') : st.dataframe(pd.concat([X_selected.head(50), y.loc[X_selected.head(50).index]], axis=1)) #---------------------------------------- # Entrenamiento #---------------------------------------- st.header('Entrenamiento') if is_numeric : algorithm = st.selectbox("Algoritmo de aprendizaje automático", options=[ "Regresión lineal", "Árbol de decisión", ], index=None ) else : algorithm = st.selectbox("Algoritmo de aprendizaje automático", options=[ "Máquinas de soporte vectorial", "Naive Bayes", "Árbol de decisión", ], index=None ) if algorithm is None : st.info('Elige un algoritmo de __aprendizaje automático__', icon=":material/north:") st.stop() st.success(f'Has seleccionado el algoritmo __{algorithm}__') from sklearn.model_selection import train_test_split train, test = train_test_split(X_selected, test_size=0.2, random_state=42) if is_numeric : from sklearn.metrics import r2_score if algorithm == "Regresión lineal" : from sklearn.linear_model import LinearRegression model = LinearRegression() elif algorithm == "Árbol de decisión" : from sklearn.tree import DecisionTreeRegressor model = DecisionTreeRegressor(random_state=42) ellapsed = time.time() model.fit(train, y.loc[train.index]) y_pred = model.predict(test) ellapsed = time.time() - ellapsed r2 = r2_score(y.loc[test.index], y_pred) * 100 r2 = max(r2, 0) col1, col2, col3 = st.columns(3) col1.container(border=True).metric("Calidad (R²)", f"{r2:.1f}%") col2.container(border=True).metric("Tiempo (s)", f"{ellapsed:.3f}") else : from sklearn.metrics import accuracy_score, classification_report if algorithm == "Naive Bayes": from sklearn.naive_bayes import GaussianNB model = GaussianNB() elif algorithm == "Árbol de decisión": from sklearn.tree import DecisionTreeClassifier model = DecisionTreeClassifier(random_state=42) elif algorithm == "Máquinas de soporte vectorial": from sklearn.svm import SVC model = SVC() ellapsed = time.time() model.fit(train, y.loc[train.index]) y_pred = model.predict(test) ellapsed = time.time() - ellapsed accuracy = accuracy_score(y.loc[test.index], y_pred) * 100 accuracy = max(accuracy, 0) col1, col2 = st.columns(2) col1.container(border=True).metric("Calidad (exactitud)", f"{accuracy:.1f}%") col2.container(border=True).metric("Tiempo (s)", f"{ellapsed:.3f}") st.success('¡Modelo entrenado!', icon=':material/check:') #---------------------------------------- # Predicción #---------------------------------------- st.header('Predicción') st.info('Introduce valores para las variables seleccionadas y obtén una predicción', icon=':material/south:') input_data = {} for i, col_name in enumerate(selected): if pd.api.types.is_numeric_dtype(X[col_name]): input_data[col_name] = st.number_input(col_name, value=float(X[col_name].mean())) else: input_data[col_name] = st.selectbox(col_name, X[col_name].unique()) input_df = pd.DataFrame([input_data]) input_df = pd.get_dummies(input_df, drop_first=True) for col in X_selected.columns: if col not in input_df.columns: input_df[col] = 0 input_df = input_df[X_selected.columns] model.fit(X_selected, y) if st.button('Realizar predicción', type='primary', icon=":material/wand_stars:", width='stretch') : prediction = model.predict(input_df)[0] st.success(f'Predicción: __{prediction:.2f}__' if is_numeric else f'Predicción: __{prediction}__', icon=":material/check:")