BulatF commited on
Commit
0925d42
·
verified ·
1 Parent(s): 4a3adc6

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +183 -0
app.py ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import plotly.express as px
4
+
5
+ def main():
6
+ st.set_page_config(page_title="Enhanced CSV to Map", layout="wide")
7
+ st.title("📍 Enhanced CSV to Interactive Map")
8
+ st.write("""
9
+ Upload a CSV file, select the latitude and longitude columns, customize the map settings, and visualize the points on an interactive map.
10
+ """)
11
+
12
+ # File uploader
13
+ uploaded_file = st.file_uploader("Choose a CSV file", type=["csv"])
14
+
15
+ if uploaded_file is not None:
16
+ try:
17
+ # Read the CSV file
18
+ df = pd.read_csv(uploaded_file)
19
+
20
+ st.success("File uploaded successfully!")
21
+ st.write("### Preview of the Data")
22
+ st.dataframe(df.head())
23
+
24
+ # Identify numeric columns for latitude and longitude
25
+ numeric_columns = df.select_dtypes(include=['float64', 'int64']).columns.tolist()
26
+
27
+ if len(numeric_columns) < 2:
28
+ st.error("The uploaded CSV does not contain enough numeric columns for latitude and longitude.")
29
+ return
30
+
31
+ # Select latitude and longitude columns
32
+ col1, col2 = st.columns(2)
33
+
34
+ with col1:
35
+ lat_col = st.selectbox("Select Latitude Column", options=numeric_columns, key="lat")
36
+
37
+ with col2:
38
+ lon_col = st.selectbox("Select Longitude Column", options=numeric_columns, key="lon")
39
+
40
+ if lat_col and lon_col:
41
+ # Validate latitude and longitude ranges
42
+ if not df[lat_col].between(-90, 90).all():
43
+ st.warning("Some latitude values are out of the valid range (-90 to 90).")
44
+ if not df[lon_col].between(-180, 180).all():
45
+ st.warning("Some longitude values are out of the valid range (-180 to 180).")
46
+
47
+ # Drop rows with missing or invalid coordinates
48
+ valid_df = df.dropna(subset=[lat_col, lon_col])
49
+ valid_df = valid_df[
50
+ (valid_df[lat_col].between(-90, 90)) &
51
+ (valid_df[lon_col].between(-180, 180))
52
+ ]
53
+
54
+ if valid_df.empty:
55
+ st.error("No valid data points to display on the map.")
56
+ return
57
+
58
+ st.write(f"### Displaying {len(valid_df)} Points on the Map")
59
+
60
+ # Sidebar for Map Settings
61
+ st.sidebar.header("🗺️ Map Settings")
62
+
63
+ # Bubble Size Selection
64
+ size_options = valid_df.select_dtypes(include=['float64', 'int64']).columns.tolist()
65
+ size_options.insert(0, None) # Option for no sizing
66
+ size_col = st.sidebar.selectbox("Select a column for bubble size (optional)", options=size_options)
67
+
68
+ # Hover Name Selection
69
+ hover_options = [col for col in df.columns if col not in [lat_col, lon_col]]
70
+ hover_options.insert(0, None) # Option for no hover name
71
+ hover_col = st.sidebar.selectbox("Select a column for hover name (optional)", options=hover_options)
72
+
73
+ # Color Customization
74
+ color_mode = st.sidebar.radio("Select Color Mode", options=["Single Color", "Color Scale"], index=0)
75
+ if color_mode == "Single Color":
76
+ color = st.sidebar.color_picker("Pick a color for the points", "#FF5733")
77
+ color_column = None
78
+ else:
79
+ # Allow user to select a column for color scale
80
+ color_column_options = [col for col in df.columns if col not in [lat_col, lon_col]]
81
+ color_column_options.insert(0, None)
82
+ color_column = st.sidebar.selectbox("Select a column for color scale (optional)", options=color_column_options)
83
+ color = None # Color will be determined by the color_column
84
+
85
+ # Map Style Selection
86
+ map_style_options = [
87
+ "open-street-map",
88
+ "carto-positron",
89
+ "carto-darkmatter",
90
+ "stamen-terrain",
91
+ "stamen-toner",
92
+ "stamen-watercolor",
93
+ "white-bg",
94
+ "basic",
95
+ "light",
96
+ "dark",
97
+ "satellite",
98
+ "satellite-streets",
99
+ "outdoors",
100
+ "traffic-day",
101
+ "traffic-night"
102
+ ]
103
+ map_style = st.sidebar.selectbox("Select Map Style", options=map_style_options, index=0)
104
+
105
+ # Default Bubble Size
106
+ default_size = st.sidebar.slider("Default Bubble Size (when no size column selected)", min_value=5, max_value=20, value=10)
107
+
108
+ # Map Height Adjustment
109
+ map_height = st.sidebar.slider("Map Height (pixels)", min_value=400, max_value=1000, value=600)
110
+
111
+ # Initial Zoom Level
112
+ zoom_level = st.sidebar.slider("Initial Zoom Level", min_value=1, max_value=20, value=3)
113
+
114
+ # Create the map based on color mode
115
+ if color_mode == "Color Scale" and color_column:
116
+ # Color Scale Mode with a selected color column
117
+ color_param = color_column
118
+ color_discrete_sequence = None
119
+ color_continuous_scale = "Viridis"
120
+ elif color_mode == "Color Scale" and not color_column:
121
+ # Color Scale Mode without a selected color column
122
+ color_param = None
123
+ color_discrete_sequence = "Viridis"
124
+ color_continuous_scale = None
125
+ elif color_mode == "Single Color":
126
+ # Single Color Mode
127
+ color_param = None
128
+ color_discrete_sequence = [color]
129
+ color_continuous_scale = None
130
+
131
+ # Create the map
132
+ if size_col:
133
+ fig = px.scatter_mapbox(
134
+ valid_df,
135
+ lat=lat_col,
136
+ lon=lon_col,
137
+ size=size_col,
138
+ size_max=15,
139
+ color=color_param,
140
+ color_continuous_scale=color_continuous_scale,
141
+ color_discrete_sequence=color_discrete_sequence,
142
+ hover_name=hover_col if hover_col else None,
143
+ hover_data=[col for col in valid_df.columns if col not in [lat_col, lon_col]],
144
+ zoom=zoom_level,
145
+ mapbox_style=map_style,
146
+ height=map_height,
147
+ title="Interactive Map"
148
+ )
149
+ else:
150
+ fig = px.scatter_mapbox(
151
+ valid_df,
152
+ lat=lat_col,
153
+ lon=lon_col,
154
+ color=color_param,
155
+ color_continuous_scale=color_continuous_scale,
156
+ color_discrete_sequence=color_discrete_sequence,
157
+ hover_name=hover_col if hover_col else None,
158
+ hover_data=[col for col in valid_df.columns if col not in [lat_col, lon_col]],
159
+ zoom=zoom_level,
160
+ mapbox_style=map_style,
161
+ height=map_height,
162
+ title="Interactive Map"
163
+ )
164
+ if color_mode == "Single Color":
165
+ # Update marker color directly
166
+ fig.update_traces(marker=dict(color=color))
167
+
168
+ # Update layout for better aesthetics
169
+ fig.update_layout(
170
+ margin={"r":0,"t":30,"l":0,"b":0},
171
+ title_x=0.5
172
+ )
173
+
174
+ st.plotly_chart(fig, use_container_width=True)
175
+
176
+ except Exception as e:
177
+ st.error(f"An error occurred while processing the file: {e}")
178
+
179
+ else:
180
+ st.info("Awaiting CSV file upload.")
181
+
182
+ if __name__ == "__main__":
183
+ main()