Spaces:
Sleeping
Sleeping
File size: 5,429 Bytes
3b45348 8567ba1 3b45348 8567ba1 3b45348 723bba7 3b45348 723bba7 3b45348 71a36bf 3b45348 723bba7 3b45348 71a36bf c7734b6 71a36bf c7734b6 3b45348 723bba7 3b45348 723bba7 71a36bf 723bba7 71a36bf 723bba7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
import pandas as pd
import folium
from folium.plugins import MarkerCluster, HeatMap
import plotly.graph_objects as go
import plotly.express as px
from geopy.geocoders import Nominatim
from geopy.exc import GeocoderInsufficientPrivileges
import re
import streamlit as st
import time
# Streamlit title and description
st.title("米其林餐廳指南分析")
st.write("分析餐廳數據,可視化區域分佈,並在地圖上顯示位置和餐廳數量熱力圖。")
# Read data from Google Sheets
sheet_id = "1xUfnD1WCF5ldqECI8YXIko1gCpaDDCwTztL17kjI42U"
df = pd.read_csv(f"https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv")
# Print column names and first few rows
st.write("資料框的列名:", df.columns.tolist())
st.write("資料預覽:")
st.dataframe(df.head())
# Initialize Nominatim geocoder
geolocator = Nominatim(user_agent="my_unique_app/3.0")
# Function to extract region (區域) from the address using regex
def extract_region(address):
match = re.search(r'(.*?)區|縣|市', address)
if match:
return match.group(0)
else:
return "Unknown"
# Function to get latitude and longitude with caching
@st.cache_data
def get_lat_lon(district):
try:
location = geolocator.geocode(f"台南市{district}")
if location:
time.sleep(1) # Delay to avoid rate limiting
return location.latitude, longitude
except GeocoderInsufficientPrivileges:
st.error("地理編碼器遇到權限問題,請稍後再試。")
return None, None
# Assuming we have a column that represents the region or can be used to derive it
# If we don't have such a column, we'll need to skip this part
if '區域' in df.columns:
region_column = '區域'
elif '地址' in df.columns:
df['區域'] = df['地址'].apply(extract_region)
region_column = '區域'
else:
st.error("無法找到區域資訊,某些分析將無法進行。")
region_column = None
# Group the data by region and count the number of restaurants
if region_column:
region_group = df.groupby(region_column).size().reset_index(name='Count')
# Create hierarchical data for the Sunburst chart
region_group['Total'] = 'All Regions' # Add a root level
hierarchical_data = region_group[['Total', region_column, 'Count']]
# Plot interactive Sunburst chart
sunburst = go.Figure(go.Sunburst(
labels=hierarchical_data[region_column].tolist() + hierarchical_data['Total'].tolist(),
parents=hierarchical_data['Total'].tolist() + [''],
values=hierarchical_data['Count'].tolist() + [hierarchical_data['Count'].sum()],
branchvalues="total",
hovertemplate='<b>%{label}</b><br>餐廳數量: %{value}<extra></extra>',
maxdepth=2,
))
sunburst.update_layout(
title="餐廳分佈(點擊可放大查看)",
title_x=0.5,
title_font=dict(size=24, family="Arial"),
height=600,
margin=dict(t=50, b=50, l=0, r=0)
)
st.subheader("餐廳分佈(Sunburst 圖)")
st.plotly_chart(sunburst, use_container_width=True)
# Plot bar chart with custom colors and labels
bar_chart = go.Figure(go.Bar(
x=region_group[region_column],
y=region_group["Count"],
text=region_group["Count"],
textposition='auto',
marker=dict(color=px.colors.qualitative.Set2)
))
bar_chart.update_layout(
title="各區域餐廳數量",
title_x=0.5,
title_font=dict(size=24, family="Arial"),
height=400,
margin=dict(t=50, b=50, l=50, r=50),
xaxis_title="區域",
yaxis_title="餐廳數量",
xaxis=dict(tickangle=-45)
)
st.subheader("各區域餐廳數量(條形圖)")
st.plotly_chart(bar_chart)
# Display a map using Folium if we have latitude and longitude
if '緯度' in df.columns and '經度' in df.columns:
st.subheader("餐廳位置地圖(含數量熱力圖)")
# Create map centered around the mean latitude and longitude
center_lat = df['緯度'].mean()
center_lon = df['經度'].mean()
m = folium.Map(location=[center_lat, center_lon], zoom_start=12)
# Add marker cluster to the map
marker_cluster = MarkerCluster().add_to(m)
# Prepare data for heatmap
heat_data = []
for index, row in df.iterrows():
if pd.notnull(row["緯度"]) and pd.notnull(row["經度"]):
folium.Marker(
location=[row["緯度"], row["經度"]],
popup=f"{row.get('店名', 'Unknown')}",
tooltip=row.get('地址', 'Unknown')
).add_to(marker_cluster)
heat_data.append([row["緯度"], row["經度"], 1]) # Weight of 1 for each restaurant
# Add heatmap layer
HeatMap(heat_data, radius=15, blur=10, max_zoom=1, name="餐廳數量熱力圖").add_to(m)
# Add layer control
folium.LayerControl().add_to(m)
# Display the map in Streamlit
st.components.v1.html(m._repr_html_(), height=600)
else:
st.error("無法顯示地圖,因為缺少緯度和經度資訊。")
# Save the DataFrame to CSV with UTF-8 encoding
csv_file = "restaurants_data.csv"
df.to_csv(csv_file, encoding="utf-8-sig", index=False)
# Display download button for the CSV
st.download_button(
label="下載餐廳數據 CSV 檔案",
data=open(csv_file, "rb").read(),
file_name=csv_file,
mime="text/csv"
) |