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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 导入必要的库
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()