import streamlit as st import pandas as pd import numpy as np from sklearn.neighbors import KNeighborsRegressor from geopy.distance import geodesic import googlemaps from geopy.exc import GeocoderTimedOut # Function to calculate distance in meters between two coordinates def calculate_distance(lat1, lon1, lat2, lon2): coords_1 = (lat1, lon1) coords_2 = (lat2, lon2) return geodesic(coords_1, coords_2).meters # Function to apply KNN and return Vunit values def knn_predict(df, target_column, features_columns, k=5): # Separate features and target variable X = df[features_columns] y = df[target_column] # Create KNN regressor knn = KNeighborsRegressor(n_neighbors=k) # Fit the model knn.fit(X, y) # Use the model to predict Vunit for the filtered_data predictions = knn.predict(df[features_columns]) return predictions # Set wide mode st.set_page_config(layout="wide") # Set dark theme st.markdown( """ """, unsafe_allow_html=True ) # Create a DataFrame with sample data data = pd.read_excel('ven_ter_fim_PEDÓ.xlsx') # Initialize variables to avoid NameError selected_coords = 'Custom' radius_visible = True custom_lat = data['latitude'].mean() custom_lon = data['longitude'].mean() radius_in_meters = 1000 filtered_data = data # Initialize with the entire dataset # Find the maximum distance between coordinates max_distance = 0 for index, row in data.iterrows(): distance = calculate_distance(row['latitude'], row['longitude'], data['latitude'].mean(), data['longitude'].mean()) if distance > max_distance: max_distance = distance # Calculate a zoom level based on the maximum distance zoom_level = round(15 - np.log10(max_distance)) # Create a sidebar for controls with st.sidebar: st.title('avalia.se') selected_coords = st.selectbox('Selecione Coordenadas', ['Random', 'Custom']) if selected_coords == 'Custom': custom_address = st.text_input('Informe o endereço', 'Endereço desejado aqui') radius_visible = True # Show radius slider for custom coordinates # No need to initialize max_distance_all here else: custom_address = "Lajeado, Rio Grande do Sul, Brazil" # Default address radius_visible = False # Hide radius slider for random coordinates max_distance_all = 0 # Initialize max_distance_all here max_distance_all = 0 # Initialize max_distance_all here # Geocode the custom address using the Google Maps API gmaps = googlemaps.Client(key='AIzaSyDoJ6C7NE2CHqFcaHTnhreOfgJeTk4uSH0') # Replace with your API key try: location = gmaps.geocode(custom_address)[0]['geometry']['location'] custom_lat, custom_lon = location['lat'], location['lng'] except (IndexError, GeocoderTimedOut): st.error("Erro: Não foi possível geocodificar o endereço fornecido. Por favor, verifique e tente novamente.") # Slider for setting the zoom level if selected_coords == 'Custom': zoom_level = st.slider('Nível de zoom', min_value=1, max_value=15, value=zoom_level) else: for index, row in data.iterrows(): distance_all = calculate_distance(row['latitude'], row['longitude'], data['latitude'].mean(), data['longitude'].mean()) if distance_all > max_distance_all: max_distance_all = distance_all # Calculate a zoom level based on the maximum distance of the entire dataset zoom_level_all = round(15 - np.log10(max_distance_all)) # Slider for setting the zoom level based on the entire dataset zoom_level = st.slider('Nível de zoom', min_value=1, max_value=15, value=zoom_level_all) # Conditionally render the radius slider if radius_visible: radius_in_meters = st.slider('Selecione raio (em metros)', min_value=100, max_value=5000, value=1000) # Filter data based on the radius if selected_coords == 'Custom': filtered_data = data[data.apply(lambda x: calculate_distance(x['latitude'], x['longitude'], custom_lat, custom_lon), axis=1) <= radius_in_meters] filtered_data = filtered_data.dropna() # Drop rows with NaN values # Add a custom CSS class to the map container st.markdown(f"""""", unsafe_allow_html=True) # Check if KNN should be applied if selected_coords == 'Custom' and radius_visible: # Apply KNN and get predicted Vunit values predicted_vunit = knn_predict(filtered_data, 'Vunit', ['latitude', 'longitude', 'Area']) # Update with your features # Add predicted Vunit values to filtered_data filtered_data['Predicted_Vunit'] = predicted_vunit # Display the map and filtered_data with st.container(): if selected_coords == 'Custom': st.map(filtered_data, zoom=zoom_level, use_container_width=True) elif selected_coords == 'Random': st.map(data, zoom=zoom_level, use_container_width=True) # Display the predicted Vunit values if applicable if 'Predicted_Vunit' in filtered_data.columns: st.write("Valores (R$/m²) previstos com algoritmo KNN:") st.write(filtered_data[['latitude', 'longitude', 'Vunit', 'Predicted_Vunit']])