顯示地震資訊
To upload files, please first save the app
import streamlit as st
import pandas as pd
import requests
from datetime import datetime
import json
st.set_page_config(
page_title="地震資訊",
page_icon="🌍",
layout="wide"
)
st.title("🌍 地震資訊監測")
# 資料來源選擇
data_source = st.selectbox(
"選擇資料來源",
["USGS (美國地質調查局)", "中央氣象署"]
)
@st.cache_data(ttl=300) # 快取5分鐘
def get_earthquake_data_usgs():
"""獲取USGS地震資料"""
try:
# NOTE: Using corsproxy.io because we're in a WASM environment. If running locally,
# you can remove the corsproxy.io prefix. Some websites don't work with the proxy,
# in those cases try removing the proxy prefix.
url = "https://corsproxy.io/?https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson"
response = requests.get(url)
data = response.json()
earthquakes = []
for feature in data['features']:
properties = feature['properties']
geometry = feature['geometry']
earthquakes.append({
'時間': datetime.fromtimestamp(properties['time']/1000).strftime('%Y-%m-%d %H:%M:%S'),
'規模 (Magnitude)': properties['mag'] if properties['mag'] else 0,
'深度 (km)': geometry['coordinates'][2] if len(geometry['coordinates']) > 2 else 0,
'地點': properties['place'] if properties['place'] else '未知',
'經度': geometry['coordinates'][0],
'緯度': geometry['coordinates'][1],
'詳細資訊': properties['url'] if properties['url'] else ''
})
return pd.DataFrame(earthquakes)
except Exception as e:
st.error(f"獲取USGS資料時發生錯誤: {str(e)}")
return pd.DataFrame()
@st.cache_data(ttl=300) # 快取5分鐘
def get_earthquake_data_cwa():
"""獲取中央氣象署地震資料"""
try:
# NOTE: Using corsproxy.io because we're in a WASM environment. If running locally,
# you can remove the corsproxy.io prefix. Some websites don't work with the proxy,
# in those cases try removing the proxy prefix.
url = "https://corsproxy.io/?https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0015-001?Authorization=CWA-OPEN-DATA-API-KEY&format=JSON"
response = requests.get(url)
# 如果API需要金鑰,我們提供一個範例資料
sample_data = [
{
'時間': '2024-01-15 14:30:25',
'規模 (Magnitude)': 5.2,
'深度 (km)': 15.6,
'地點': '花蓮縣近海',
'經度': 121.5,
'緯度': 24.0,
'最大震度': '4級'
},
{
'時間': '2024-01-15 08:45:12',
'規模 (Magnitude)': 4.1,
'深度 (km)': 8.2,
'地點': '台東縣海端鄉',
'經度': 121.2,
'緯度': 23.1,
'最大震度': '3級'
},
{
'時間': '2024-01-14 23:15:33',
'規模 (Magnitude)': 3.8,
'深度 (km)': 12.4,
'地點': '南投縣仁愛鄉',
'經度': 121.0,
'緯度': 24.2,
'最大震度': '2級'
}
]
return pd.DataFrame(sample_data)
except Exception as e:
st.error(f"獲取中央氣象署資料時發生錯誤: {str(e)}")
return pd.DataFrame()
# 根據選擇的資料來源獲取資料
if data_source == "USGS (美國地質調查局)":
df = get_earthquake_data_usgs()
st.info("📡 顯示全球過去24小時地震資料(來源:USGS)", icon="ℹ️")
else:
df = get_earthquake_data_cwa()
st.info("📡 顯示台灣地區地震資料(來源:中央氣象署)- 範例資料", icon="ℹ️")
if not df.empty:
# 篩選選項
col1, col2 = st.columns(2)
with col1:
min_magnitude = st.slider(
"最小規模",
min_value=0.0,
max_value=10.0,
value=0.0,
step=0.1
)
with col2:
max_depth = st.slider(
"最大深度 (km)",
min_value=0,
max_value=700,
value=700,
step=10
)
# 篩選資料
filtered_df = df[
(df['規模 (Magnitude)'] >= min_magnitude) &
(df['深度 (km)'] <= max_depth)
].copy()
# 統計資訊
st.subheader("📊 統計資訊")
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("總地震數量", len(filtered_df))
with col2:
if not filtered_df.empty:
avg_magnitude = filtered_df['規模 (Magnitude)'].mean()
st.metric("平均規模", f"{avg_magnitude:.1f}")
else:
st.metric("平均規模", "N/A")
with col3:
if not filtered_df.empty:
max_magnitude = filtered_df['規模 (Magnitude)'].max()
st.metric("最大規模", f"{max_magnitude:.1f}")
else:
st.metric("最大規模", "N/A")
with col4:
if not filtered_df.empty:
avg_depth = filtered_df['深度 (km)'].mean()
st.metric("平均深度", f"{avg_depth:.1f} km")
else:
st.metric("平均深度", "N/A")
# 地震列表
st.subheader("🗂️ 地震列表")
if not filtered_df.empty:
# 按規模排序
display_df = filtered_df.sort_values('規模 (Magnitude)', ascending=False)
# 添加顏色標記
def highlight_magnitude(val):
if val >= 7.0:
return 'background-color: #ff4444; color: white'
elif val >= 5.0:
return 'background-color: #ff8800; color: white'
elif val >= 3.0:
return 'background-color: #ffaa00'
else:
return 'background-color: #88ff88'
# 顯示表格
styled_df = display_df.style.applymap(
highlight_magnitude,
subset=['規模 (Magnitude)']
)
st.dataframe(styled_df, use_container_width=True)
# 規模分布圖表
st.subheader("📈 規模分布")
magnitude_counts = pd.cut(
filtered_df['規模 (Magnitude)'],
bins=[0, 2, 3, 4, 5, 6, 7, 10],
labels=['0-2', '2-3', '3-4', '4-5', '5-6', '6-7', '7+']
).value_counts().sort_index()
st.bar_chart(magnitude_counts)
# 深度分布圖表
st.subheader("🏔️ 深度分布")
st.histogram_chart(filtered_df['深度 (km)'], bins=20)
else:
st.warning("⚠️ 沒有符合篩選條件的地震資料")
# 重要提醒
st.subheader("⚠️ 重要提醒")
st.warning("""
- 🔴 規模7.0以上:重大地震
- 🟠 規模5.0-6.9:中強地震
- 🟡 規模3.0-4.9:有感地震
- 🟢 規模3.0以下:微震
請隨時關注官方地震預警資訊!
""")
# 資料更新時間
st.caption(f"資料更新時間: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
else:
st.error("❌ 無法獲取地震資料,請稍後再試")
# 重新整理按鈕
if st.button("🔄 重新整理資料"):
st.cache_data.clear()
st.rerun()
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?