oberbics commited on
Commit
72139b5
·
verified ·
1 Parent(s): c22c6d5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -134
app.py CHANGED
@@ -100,19 +100,18 @@ def process_excel(file, places_column):
100
  if places_column not in df.columns:
101
  return None, f"Spalte '{places_column}' wurde in der Excel-Datei nicht gefunden. Verfügbare Spalten: {', '.join(df.columns)}", None
102
 
103
- # Create coordinates columns
104
- df['latitude'] = None
105
- df['longitude'] = None
106
- # Add column for structured location data
107
- df['location_data'] = None
108
 
109
  geocoder = SafeGeocoder()
110
  coords = []
111
  processed_count = 0
112
 
113
- # Process each location and store as JSON
114
  for idx, row in df.iterrows():
115
  if pd.isna(row[places_column]):
 
 
116
  continue
117
 
118
  location = str(row[places_column]).strip()
@@ -124,121 +123,61 @@ def process_excel(file, places_column):
124
  except:
125
  locations = [location]
126
 
127
- # Process all locations and store as JSON
128
- location_data = []
129
  for loc in locations:
130
  point = geocoder.get_coords(loc)
131
  if point:
132
- location_data.append({
133
- 'location': loc,
134
- 'latitude': point[0],
135
- 'longitude': point[1]
136
- })
 
 
 
 
 
137
  coords.append(point)
138
  processed_count += 1
 
139
 
140
- if location_data:
141
- df.at[idx, 'location_data'] = json.dumps(location_data)
142
- # Store first location's coordinates in main columns for compatibility
143
- df.at[idx, 'latitude'] = location_data[0]['latitude']
144
- df.at[idx, 'longitude'] = location_data[0]['longitude']
 
145
 
146
  # Create the map
147
- map_html, _ = create_map(df, places_column)
 
 
 
 
148
 
149
- # Save the updated DataFrame to a new Excel file
150
- with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as tmp:
151
- processed_path = tmp.name
152
- df.to_excel(processed_path, index=False)
 
 
 
153
 
154
- total_locations = df[places_column].count()
155
- success_rate = (processed_count / total_locations * 100) if total_locations > 0 else 0
156
 
157
- stats = f"Gefunden: {processed_count} von {total_locations} Orten ({success_rate:.1f}%)"
 
158
 
159
- return map_html, stats, processed_path
160
- except Exception as e:
161
- import traceback
162
- trace = traceback.format_exc()
163
- print(f"Error processing file: {e}\n{trace}")
164
- return None, f"Fehler bei der Verarbeitung der Datei: {str(e)}", None
165
-
166
-
167
- def create_map(df, location_col):
168
- m = folium.Map(
169
- location=[20, 0],
170
- zoom_start=2,
171
- control_scale=True
172
- )
173
-
174
- folium.TileLayer(
175
- tiles=MAP_TILES["GreenMap"]["url"],
176
- attr=MAP_TILES["GreenMap"]["attr"],
177
- name="GreenMap",
178
- overlay=False,
179
- control=False
180
- ).add_to(m)
181
-
182
- Fullscreen().add_to(m)
183
- MeasureControl(position='topright', primary_length_unit='kilometers').add_to(m)
184
-
185
- coords = []
186
- marker_cluster = MarkerCluster(name="Locations").add_to(m)
187
- processed_count = 0
188
-
189
- for idx, row in df.iterrows():
190
- # Check if we have JSON location data
191
- if 'location_data' in df.columns and not pd.isna(row['location_data']):
192
- try:
193
- # Parse the JSON location data
194
- location_data = json.loads(row['location_data'])
195
 
196
- # Process each location in the JSON data
197
- for loc_item in location_data:
198
- location_name = loc_item['location']
199
- point = (loc_item['latitude'], loc_item['longitude'])
200
-
201
- # Create additional info for popup
202
- additional_info = ""
203
- for col in df.columns:
204
- if col not in [location_col, 'location_data', 'latitude', 'longitude'] and not pd.isna(row[col]):
205
- additional_info += f"<br><b>{col}:</b> {row[col]}"
206
-
207
- # Add marker to map
208
- popup_content = f"""
209
- <div style="min-width: 200px; max-width: 300px">
210
- <h4 style="font-family: 'Source Sans Pro', sans-serif; margin-bottom: 5px;">{location_name}</h4>
211
- <div style="font-family: 'Source Sans Pro', sans-serif; font-size: 14px;">
212
- {additional_info}
213
- </div>
214
- </div>
215
- """
216
-
217
- folium.Marker(
218
- location=point,
219
- popup=folium.Popup(popup_content, max_width=300),
220
- tooltip=location_name,
221
- icon=folium.Icon(color="blue", icon="info-sign")
222
- ).add_to(marker_cluster)
223
-
224
- coords.append(point)
225
- processed_count += 1
226
- except (json.JSONDecodeError, KeyError) as e:
227
- print(f"Error processing JSON location data for row {idx}: {e}")
228
- # Continue with fallback method if JSON processing fails
229
-
230
- # Fallback to the old method if no JSON data is present
231
- elif not pd.isna(row[location_col]):
232
- location = str(row[location_col]).strip()
233
-
234
- additional_info = ""
235
- for col in df.columns:
236
- if col != location_col and not pd.isna(row[col]):
237
- additional_info += f"<br><b>{col}:</b> {row[col]}"
238
-
239
- # If we have latitude and longitude directly
240
- if 'latitude' in df.columns and 'longitude' in df.columns and not pd.isna(row['latitude']) and not pd.isna(row['longitude']):
241
- point = (row['latitude'], row['longitude'])
242
 
243
  popup_content = f"""
244
  <div style="min-width: 200px; max-width: 300px">
@@ -250,36 +189,48 @@ def create_map(df, location_col):
250
  """
251
 
252
  folium.Marker(
253
- location=point,
254
  popup=folium.Popup(popup_content, max_width=300),
255
  tooltip=location,
256
  icon=folium.Icon(color="blue", icon="info-sign")
257
  ).add_to(marker_cluster)
258
-
259
- coords.append(point)
260
- processed_count += 1
261
-
262
- if coords:
263
- m.fit_bounds(coords)
264
-
265
- custom_css = """
266
- <style>
267
- @import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap');
268
- .leaflet-container {
269
- font-family: 'Source Sans Pro', sans-serif;
270
- }
271
- .leaflet-popup-content {
272
- font-family: 'Source Sans Pro', sans-serif;
273
- }
274
- .leaflet-popup-content h4 {
275
- font-weight: 600;
276
- margin-bottom: 8px;
277
- }
278
- </style>
279
- """
280
- m.get_root().header.add_child(folium.Element(custom_css))
281
-
282
- return m._repr_html_(), processed_count
 
 
 
 
 
 
 
 
 
 
 
 
283
 
284
  # Corrected model loading function based on official usage example
285
 
 
100
  if places_column not in df.columns:
101
  return None, f"Spalte '{places_column}' wurde in der Excel-Datei nicht gefunden. Verfügbare Spalten: {', '.join(df.columns)}", None
102
 
103
+ # Create a new DataFrame to store expanded rows
104
+ expanded_rows = []
 
 
 
105
 
106
  geocoder = SafeGeocoder()
107
  coords = []
108
  processed_count = 0
109
 
110
+ # Process each row
111
  for idx, row in df.iterrows():
112
  if pd.isna(row[places_column]):
113
+ # Keep rows with no location as-is
114
+ expanded_rows.append(row.to_dict())
115
  continue
116
 
117
  location = str(row[places_column]).strip()
 
123
  except:
124
  locations = [location]
125
 
126
+ # Process each location in the comma-separated list
127
+ location_rows_added = False
128
  for loc in locations:
129
  point = geocoder.get_coords(loc)
130
  if point:
131
+ # Create a new row for this location
132
+ new_row = row.copy()
133
+ new_row_dict = new_row.to_dict()
134
+ new_row_dict[places_column] = loc # Replace with just this location
135
+ new_row_dict['latitude'] = point[0]
136
+ new_row_dict['longitude'] = point[1]
137
+
138
+ # Add the row to our expanded rows list
139
+ expanded_rows.append(new_row_dict)
140
+
141
  coords.append(point)
142
  processed_count += 1
143
+ location_rows_added = True
144
 
145
+ # If none of the locations could be geocoded, keep the original row
146
+ if not location_rows_added:
147
+ expanded_rows.append(row.to_dict())
148
+
149
+ # Convert the list of dictionaries to a DataFrame
150
+ expanded_df = pd.DataFrame(expanded_rows)
151
 
152
  # Create the map
153
+ m = folium.Map(
154
+ location=[20, 0],
155
+ zoom_start=2,
156
+ control_scale=True
157
+ )
158
 
159
+ folium.TileLayer(
160
+ tiles=MAP_TILES["GreenMap"]["url"],
161
+ attr=MAP_TILES["GreenMap"]["attr"],
162
+ name="GreenMap",
163
+ overlay=False,
164
+ control=False
165
+ ).add_to(m)
166
 
167
+ Fullscreen().add_to(m)
168
+ MeasureControl(position='topright', primary_length_unit='kilometers').add_to(m)
169
 
170
+ # Add markers directly here
171
+ marker_cluster = MarkerCluster(name="Locations").add_to(m)
172
 
173
+ for idx, row in expanded_df.iterrows():
174
+ if 'latitude' in row and 'longitude' in row and not pd.isna(row['latitude']) and not pd.isna(row['longitude']):
175
+ location = row[places_column] if not pd.isna(row[places_column]) else "Unknown"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
+ additional_info = ""
178
+ for col in expanded_df.columns:
179
+ if col not in [places_column, 'latitude', 'longitude'] and not pd.isna(row[col]):
180
+ additional_info += f"<br><b>{col}:</b> {row[col]}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
  popup_content = f"""
183
  <div style="min-width: 200px; max-width: 300px">
 
189
  """
190
 
191
  folium.Marker(
192
+ location=(row['latitude'], row['longitude']),
193
  popup=folium.Popup(popup_content, max_width=300),
194
  tooltip=location,
195
  icon=folium.Icon(color="blue", icon="info-sign")
196
  ).add_to(marker_cluster)
197
+
198
+ if coords:
199
+ m.fit_bounds(coords)
200
+
201
+ custom_css = """
202
+ <style>
203
+ @import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap');
204
+ .leaflet-container {
205
+ font-family: 'Source Sans Pro', sans-serif;
206
+ }
207
+ .leaflet-popup-content {
208
+ font-family: 'Source Sans Pro', sans-serif;
209
+ }
210
+ .leaflet-popup-content h4 {
211
+ font-weight: 600;
212
+ margin-bottom: 8px;
213
+ }
214
+ </style>
215
+ """
216
+ m.get_root().header.add_child(folium.Element(custom_css))
217
+
218
+ # Save the expanded DataFrame to Excel
219
+ with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as tmp:
220
+ processed_path = tmp.name
221
+ expanded_df.to_excel(processed_path, index=False)
222
+
223
+ total_locations = df[places_column].count()
224
+ success_rate = (processed_count / total_locations * 100) if total_locations > 0 else 0
225
+
226
+ stats = f"Gefunden: {processed_count} von {total_locations} Orten ({success_rate:.1f}%)"
227
+
228
+ return m._repr_html_(), stats, processed_path
229
+ except Exception as e:
230
+ import traceback
231
+ trace = traceback.format_exc()
232
+ print(f"Error processing file: {e}\n{trace}")
233
+ return None, f"Fehler bei der Verarbeitung der Datei: {str(e)}", None
234
 
235
  # Corrected model loading function based on official usage example
236