ricardoadriano commited on
Commit
68a9e56
·
verified ·
1 Parent(s): 63b6361

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +35 -67
src/streamlit_app.py CHANGED
@@ -2,7 +2,7 @@
2
  # coding: utf-8
3
 
4
  # =====================================================
5
- # Dashboard - AmesHousing (Tarefa 4) - versão otimizada
6
  # =====================================================
7
 
8
  import streamlit as st
@@ -28,8 +28,6 @@ st.set_page_config(
28
  layout="wide",
29
  initial_sidebar_state="expanded"
30
  )
31
-
32
- # Nova API para manter posição estável
33
  st.query_params.clear()
34
 
35
  st.markdown("<h1 style='text-align:center;color:#003366;'>Análise do Dataset AmesHousing</h1>", unsafe_allow_html=True)
@@ -45,15 +43,13 @@ def carregar_dados():
45
  "/mnt/data/AmesHousing.csv",
46
  "../Dados/AmesHousing.csv",
47
  ]
48
- last_err = None
49
  for p in paths_tentativa:
50
  try:
51
  df = pd.read_csv(p)
52
  return df
53
- except Exception as e:
54
- last_err = e
55
  continue
56
- raise RuntimeError(f"Não foi possível carregar o AmesHousing.csv. Último erro: {last_err}")
57
 
58
  casa_data = carregar_dados()
59
  casa_data.columns = casa_data.columns.str.strip().str.replace(" ", "_")
@@ -106,12 +102,9 @@ alpha_reg = st.sidebar.slider("Nível de significância (α) — Regressão", 0.
106
  # Distribuição de Preço de Venda
107
  st.subheader("Distribuição do Preço de Venda")
108
  if not dados_filtrados.empty:
109
- fig, ax = plt.subplots(figsize=(6,4))
110
  sns.histplot(dados_filtrados['SalePrice'], kde=True, ax=ax)
111
- ax.set_title("Distribuição do Preço de Venda")
112
  st.pyplot(fig, clear_figure=True, use_container_width=False)
113
- else:
114
- st.warning("Nenhum dado disponível com os filtros aplicados.")
115
 
116
  # Boxplots
117
  st.subheader("Boxplots das Variáveis Selecionadas")
@@ -119,53 +112,35 @@ variavel = st.selectbox(
119
  "Escolha a variável categórica para comparar preços:",
120
  ["Neighborhood","Garage_Type","Fireplaces"]
121
  )
122
-
123
- if not dados_filtrados.empty:
124
- if len(dados_filtrados[variavel].dropna().unique()) > 1:
125
- fig2, ax2 = plt.subplots(figsize=(8,5))
126
- sns.boxplot(x=variavel, y="SalePrice", data=dados_filtrados, ax=ax2)
127
- plt.xticks(rotation=90)
128
- ax2.set_title(f"Preço de Venda por {variavel}")
129
- st.pyplot(fig2, clear_figure=True, use_container_width=False)
130
- else:
131
- st.warning(f"Não é possível gerar boxplot: apenas uma categoria em {variavel} após os filtros.")
132
 
133
  # Scatter interativo
134
  st.subheader("Preço Médio de Venda por Bairro")
135
- @st.cache_data
136
- def agrupar_bairros(df):
137
- return df.groupby('Neighborhood').agg(
138
  count=('SalePrice','size'),
139
  mean_price=('SalePrice','mean')
140
  ).reset_index()
141
-
142
- if not dados_filtrados.empty:
143
- bairro_grouped = agrupar_bairros(dados_filtrados)
144
  bairro_filtered = bairro_grouped[bairro_grouped['count'] >= 5]
145
  if not bairro_filtered.empty:
146
  fig3 = px.scatter(
147
  bairro_filtered,
148
- x='mean_price',
149
- y='Neighborhood',
150
- size='count',
151
- color='Neighborhood',
152
- title='Preço Médio de Venda vs Bairro (Ames, Iowa)',
153
- labels={'mean_price': 'Preço Médio de Venda', 'Neighborhood':'Bairro'},
154
- opacity=0.8
155
  )
156
- fig3.update_layout(height=400, width=700)
157
  st.plotly_chart(fig3, use_container_width=False)
158
- else:
159
- st.warning("Não há bairros suficientes após filtros para gerar o gráfico.")
160
 
161
  # =================================================
162
  # Regressão Linear — Tarefa 4
163
  # =================================================
164
-
165
  def construir_formula(y, feats_num, feats_cat, inter_1=None, inter_2=None):
166
- termos = []
167
- termos += feats_num
168
- termos += [f"C({c})" for c in feats_cat]
169
  if inter_1 and inter_2:
170
  a = f"C({inter_1})" if inter_1 in feats_cat else inter_1
171
  b = f"C({inter_2})" if inter_2 in feats_cat else inter_2
@@ -178,48 +153,41 @@ if st.button("Ajustar modelo"):
178
  if interagir and inter_1 and inter_2:
179
  cols_necessarias += [inter_1, inter_2]
180
  df_modelo = dados_filtrados[cols_necessarias].dropna().copy()
181
- if df_modelo.empty:
182
- st.error("Sem dados suficientes após remoção de NAs nas variáveis selecionadas.")
183
- else:
184
  y_col = 'SalePrice'
185
  if usar_logy:
186
- df_modelo['SalePrice'] = np.log(df_modelo['SalePrice'].astype(float))
187
- y_col = 'SalePrice'
188
-
189
  formula = construir_formula(y_col, feats_num, feats_cat, inter_1 if interagir else None, inter_2 if interagir else None)
190
  df_treino, df_teste = train_test_split(df_modelo, test_size=teste_size, random_state=42)
191
  model = ols(formula, data=df_treino).fit()
192
 
193
- st.markdown("#### Especificação do Modelo")
194
  st.code(formula)
195
- st.markdown("#### Coeficientes e Inferência")
196
- st.dataframe(model.summary2().tables[1])
197
 
198
- # Métricas
199
- y_true = df_teste['SalePrice']
200
- y_pred = model.predict(df_teste)
201
  if usar_logy:
202
- y_true = np.exp(y_true)
203
- y_pred = np.exp(y_pred)
204
- R2 = r2_score(y_true, y_pred)
205
- RMSE = mean_squared_error(y_true, y_pred, squared=False)
206
- MAE = mean_absolute_error(y_true, y_pred)
207
- st.dataframe(pd.DataFrame({'Métrica':['R²','RMSE','MAE'],'Valor':[R2,RMSE,MAE]}))
208
-
209
- # Gráficos diagnósticos fixos
210
- residuos = model.resid
211
- fitted = model.fittedvalues
 
212
  cols = st.columns(3)
213
  with cols[0]:
214
- fig_r, ax_r = plt.subplots(figsize=(3.5,3))
215
  ax_r.scatter(fitted, residuos, alpha=0.5)
216
  ax_r.axhline(0, color='red', linestyle='--')
217
  st.pyplot(fig_r, clear_figure=True, use_container_width=False)
218
  with cols[1]:
219
- fig_q = sm.qqplot(residuos, line='45', fit=True)
220
- fig_q.set_size_inches(3.5,3)
221
  st.pyplot(fig_q, clear_figure=True, use_container_width=False)
222
  with cols[2]:
223
- fig_h, ax_h = plt.subplots(figsize=(3.5,3))
224
  sns.histplot(residuos, kde=True, ax=ax_h)
225
  st.pyplot(fig_h, clear_figure=True, use_container_width=False)
 
2
  # coding: utf-8
3
 
4
  # =====================================================
5
+ # Dashboard - AmesHousing (Tarefa 4) - versão compacta
6
  # =====================================================
7
 
8
  import streamlit as st
 
28
  layout="wide",
29
  initial_sidebar_state="expanded"
30
  )
 
 
31
  st.query_params.clear()
32
 
33
  st.markdown("<h1 style='text-align:center;color:#003366;'>Análise do Dataset AmesHousing</h1>", unsafe_allow_html=True)
 
43
  "/mnt/data/AmesHousing.csv",
44
  "../Dados/AmesHousing.csv",
45
  ]
 
46
  for p in paths_tentativa:
47
  try:
48
  df = pd.read_csv(p)
49
  return df
50
+ except:
 
51
  continue
52
+ return pd.DataFrame()
53
 
54
  casa_data = carregar_dados()
55
  casa_data.columns = casa_data.columns.str.strip().str.replace(" ", "_")
 
102
  # Distribuição de Preço de Venda
103
  st.subheader("Distribuição do Preço de Venda")
104
  if not dados_filtrados.empty:
105
+ fig, ax = plt.subplots(figsize=(5,3.5))
106
  sns.histplot(dados_filtrados['SalePrice'], kde=True, ax=ax)
 
107
  st.pyplot(fig, clear_figure=True, use_container_width=False)
 
 
108
 
109
  # Boxplots
110
  st.subheader("Boxplots das Variáveis Selecionadas")
 
112
  "Escolha a variável categórica para comparar preços:",
113
  ["Neighborhood","Garage_Type","Fireplaces"]
114
  )
115
+ if not dados_filtrados.empty and len(dados_filtrados[variavel].dropna().unique()) > 1:
116
+ fig2, ax2 = plt.subplots(figsize=(6,4))
117
+ sns.boxplot(x=variavel, y="SalePrice", data=dados_filtrados, ax=ax2)
118
+ plt.xticks(rotation=90)
119
+ st.pyplot(fig2, clear_figure=True, use_container_width=False)
 
 
 
 
 
120
 
121
  # Scatter interativo
122
  st.subheader("Preço Médio de Venda por Bairro")
123
+ if not dados_filtrados.empty:
124
+ bairro_grouped = dados_filtrados.groupby('Neighborhood').agg(
 
125
  count=('SalePrice','size'),
126
  mean_price=('SalePrice','mean')
127
  ).reset_index()
 
 
 
128
  bairro_filtered = bairro_grouped[bairro_grouped['count'] >= 5]
129
  if not bairro_filtered.empty:
130
  fig3 = px.scatter(
131
  bairro_filtered,
132
+ x='mean_price', y='Neighborhood',
133
+ size='count', color='Neighborhood',
134
+ labels={'mean_price': 'Preço Médio de Venda', 'Neighborhood':'Bairro'}
 
 
 
 
135
  )
136
+ fig3.update_layout(width=600, height=350)
137
  st.plotly_chart(fig3, use_container_width=False)
 
 
138
 
139
  # =================================================
140
  # Regressão Linear — Tarefa 4
141
  # =================================================
 
142
  def construir_formula(y, feats_num, feats_cat, inter_1=None, inter_2=None):
143
+ termos = feats_num + [f"C({c})" for c in feats_cat]
 
 
144
  if inter_1 and inter_2:
145
  a = f"C({inter_1})" if inter_1 in feats_cat else inter_1
146
  b = f"C({inter_2})" if inter_2 in feats_cat else inter_2
 
153
  if interagir and inter_1 and inter_2:
154
  cols_necessarias += [inter_1, inter_2]
155
  df_modelo = dados_filtrados[cols_necessarias].dropna().copy()
156
+ if not df_modelo.empty:
 
 
157
  y_col = 'SalePrice'
158
  if usar_logy:
159
+ df_modelo['SalePrice'] = np.log(df_modelo['SalePrice'])
 
 
160
  formula = construir_formula(y_col, feats_num, feats_cat, inter_1 if interagir else None, inter_2 if interagir else None)
161
  df_treino, df_teste = train_test_split(df_modelo, test_size=teste_size, random_state=42)
162
  model = ols(formula, data=df_treino).fit()
163
 
 
164
  st.code(formula)
165
+ st.dataframe(model.summary2().tables[1], use_container_width=False, height=200)
 
166
 
167
+ y_true, y_pred = df_teste['SalePrice'], model.predict(df_teste)
 
 
168
  if usar_logy:
169
+ y_true, y_pred = np.exp(y_true), np.exp(y_pred)
170
+ metrics = pd.DataFrame({
171
+ 'Métrica': ['R²','RMSE','MAE'],
172
+ 'Valor': [r2_score(y_true, y_pred),
173
+ mean_squared_error(y_true, y_pred, squared=False),
174
+ mean_absolute_error(y_true, y_pred)]
175
+ })
176
+ st.dataframe(metrics, use_container_width=False, height=120)
177
+
178
+ # Gráficos diagnósticos
179
+ residuos, fitted = model.resid, model.fittedvalues
180
  cols = st.columns(3)
181
  with cols[0]:
182
+ fig_r, ax_r = plt.subplots(figsize=(3,3))
183
  ax_r.scatter(fitted, residuos, alpha=0.5)
184
  ax_r.axhline(0, color='red', linestyle='--')
185
  st.pyplot(fig_r, clear_figure=True, use_container_width=False)
186
  with cols[1]:
187
+ fig_q, ax_q = plt.subplots(figsize=(3,3))
188
+ sm.qqplot(residuos, line='45', fit=True, ax=ax_q)
189
  st.pyplot(fig_q, clear_figure=True, use_container_width=False)
190
  with cols[2]:
191
+ fig_h, ax_h = plt.subplots(figsize=(3,3))
192
  sns.histplot(residuos, kde=True, ax=ax_h)
193
  st.pyplot(fig_h, clear_figure=True, use_container_width=False)