You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
3.9 KiB

# 导入必要的库
import requests
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import folium
from folium.plugins import HeatMap
import streamlit as st
from datetime import datetime, timedelta
# 第一步:数据收集
def fetch_earthquake_data(min_magnitude=4.5, start_time=None, end_time=None):
url = 'https://earthquake.usgs.gov/fdsnws/event/1/query'
if not start_time:
start_time = (datetime.utcnow() - timedelta(days=30)).strftime("%Y-%m-%d")
if not end_time:
end_time = datetime.utcnow().strftime("%Y-%m-%d")
params = {
'format': 'geojson',
'starttime': start_time,
'endtime': end_time,
'minmagnitude': min_magnitude
}
response = requests.get(url, params=params)
data = response.json()
features = data['features']
# 提取所需信息
earthquakes = []
for feature in features:
properties = feature['properties']
geometry = feature['geometry']
earthquakes.append({
'time': pd.to_datetime(properties['time'], unit='ms'),
'place': properties['place'],
'magnitude': properties['mag'],
'depth': geometry['coordinates'][2],
'latitude': geometry['coordinates'][1],
'longitude': geometry['coordinates'][0]
})
return pd.DataFrame(earthquakes)
# 第二步:数据分析和可视化函数
def plot_magnitude_distribution(df):
plt.figure(figsize=(10, 6))
sns.histplot(df['magnitude'], bins=20, kde=True)
plt.title('magnitude distribution histogram')
plt.xlabel('magnitude')
plt.ylabel('frequency')
st.pyplot(plt)
def plot_time_series(df):
df_time = df.set_index('time').resample('D').count()
plt.figure(figsize=(10, 6))
plt.plot(df_time.index, df_time['magnitude'])
plt.title('daily earthquake count time series')
plt.xlabel('date')
plt.ylabel('number of earthquakes')
st.pyplot(plt)
def create_interactive_map(df):
map_center = [df['latitude'].mean(), df['longitude'].mean()]
base_map = folium.Map(location=map_center, zoom_start=2)
# 添加地震位置点
for _, row in df.iterrows():
folium.CircleMarker(
location=[row['latitude'], row['longitude']],
radius=row['magnitude'] * 1.5,
popup=f"Magnitude: {row['magnitude']}, Depth: {row['depth']} km",
color='red',
fill=True,
fill_color='red'
).add_to(base_map)
# 添加热力图
heat_data = [[row['latitude'], row['longitude']] for _, row in df.iterrows()]
HeatMap(heat_data).add_to(base_map)
return base_map
# 第三步制作Streamlit应用
def main(streamlit_folium=None):
st.title("全球地震数据分析与可视化")
# 侧边栏参数选择
st.sidebar.header("参数设置")
min_magnitude = st.sidebar.slider("最小震级", 0.0, 10.0, 4.5, 0.1)
days = st.sidebar.slider("过去多少天的数据", 1, 90, 30)
# 获取数据
start_time = (datetime.utcnow() - timedelta(days=days)).strftime("%Y-%m-%d")
end_time = datetime.utcnow().strftime("%Y-%m-%d")
df = fetch_earthquake_data(min_magnitude=min_magnitude, start_time=start_time, end_time=end_time)
st.subheader(f"{start_time}{end_time},震级大于{min_magnitude}的地震数据,共{len(df)}")
st.map(df[['latitude', 'longitude']])
# 显示数据表
if st.checkbox("显示原始数据表"):
st.write(df)
# 震级分布直方图
st.subheader("震级分布直方图")
plot_magnitude_distribution(df)
# 时间序列图
st.subheader("每日地震数量时间序列")
plot_time_series(df)
# 交互式地图
st.subheader("地震分布交互式地图")
folium_map = create_interactive_map(df)
# 将Folium地图嵌入Streamlit
from streamlit_folium import st_folium
st_data = st_folium(folium_map, width=700)
if __name__ == "__main__":
main()