Plotly提供了根据位置绘制地图的工具。将使用它来使用它来进行可视化并指出全球地震分布情况。
地震数据
地震是一里氏震级度量的,而该文件记录了最近24小时内全球发生所有不低于1级的地震。
查看json数据
模块json提供各种探索和处理JSON数据的工具,其中有一些助于重新设置这个文件的格式,让我们能够清楚地查看原始数据,继而决定如何以编程的方式来处理。
先加载这个些数据并将其以易于阅读的方式显示出来。这个数据文件很长,因此不打印出来,而是将数据写入另一个文件,再打开该文件并轻松地再数据中导航:
import json
# 探索数据的结构。
filename = './eq_data_1_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
reader_file = 'readable_eq_data.json'
with open(reader_file,'w') as f:
json.dump(all_eq_data,f,indent=4)
导入json以便恰当的加载文件中的数据。并将其存储到all_eq_data中.函数json.load()将数据转换成为Python能够处理的格式,这里是一个庞大的字典。后创建一个文件,以便将这些易于阅读的方式写入其中。函数json.dump()接受一个JSON数据对象和一个文件对象,并将数据写入这个文件中,参数indent=4让dump()使用与数据结构匹配的缩进来设置数据格式。
这个文件的开头是一个键为“metadata”的片段,指出了这个数据文件是什么时候生成的,以及能够在网上什么地方找到,它还包括适合人类阅读的标题以及文件中记录了多少次地震:在过去24小时内,发生了158次地震。
这个geoJSON文件的结构适合存储基于位置的数据。数据存储在一个与键"features"相关联的列表中。这个文件包含的是地震数据。因此列表的每个元素都对应于一次地震。这种结构很有用,让地质学家能够将有关每次地震的任意数量信息存储在一个字典中,在将这些字典放在一个大型列表中。
表示地政的字典:
{
"type": "Feature",
"properties": {
"mag": 0.96,
"place": "8km NE of Aguanga, CA",
"time": 1550360775470,
"updated": 1550360993593,
"tz": -480,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/ci37532978",
"detail": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/detail/ci37532978.geojson",
"felt": null,
"cdi": null,
"mmi": null,
"alert": null,
"status": "automatic",
"tsunami": 0,
"sig": 14,
"net": "ci",
"code": "37532978",
"ids": ",ci37532978,",
"sources": ",ci,",
"types": ",geoserve,nearby-cities,origin,phase-data,",
"nst": 32,
"dmin": 0.02648,
"rms": 0.15,
"gap": 37,
"magType": "ml",
"type": "earthquake",
"title": "M 1.0 - 8km NE of Aguanga, CA"
},
"geometry": {
"type": "Point",
"coordinates": [
-116.7941667,
33.4863333,
3.22
]
},
"id": "ci37532978"
},
键"properties"关联到了与特定地震相关的大量信息。主要关心键"mag"相关联的地震震级以及地震的标题,因为后者很好地概述了地震的震级和位置。
键"geometry"指出了地震发生在什么地方,我们需要根据这项信息将地震在散点图上标出来,在与键"conordinates"相关联的列表中,可以找出地震发生位置的经度和纬度。
首先提取过去24小时内发生的每次地震对应的字典:
创建地震列表
首先创建一个列表,其中包含所有地震的各种信息:
import json
# 探索数据的结构。
filename = './eq_data_1_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
# reader_file = 'readable_eq_data.json'
# with open(reader_file,'w') as f:
# json.dump(all_eq_data,f,indent=4)
all_eq_dicts = all_eq_data['features']
print(len(all_eq_dicts))
提取与键'features'相关联的数据,并将其存储到all_eq_dicts中。
提取震级
有了包含所有地震数据的列表之后,就可以遍历这个列表,从中提取所需的数据。下面提取每次地震的震级:
import json
# 探索数据的结构。
filename = './eq_data_1_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
# reader_file = 'readable_eq_data.json'
# with open(reader_file,'w') as f:
# json.dump(all_eq_data,f,indent=4)
all_eq_dicts = all_eq_data['features']
mags = []
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
mags.append(mag)
print(mags[:10])
每次地震的震级都存储在相应字典‘properties’部分的‘mag’键下,依次将地震震级赋给遍历mag,再将这个变量附加到列表mags末尾。
提取位置数据
位置数据存储在了“geometry”键下。在“geometry”键关联的字典中,有一个“coordinates”键,它关联到了一个列表,而列表中的前两个值为经度和纬度。
import json
# 探索数据的结构。
filename = './eq_data_1_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
# reader_file = 'readable_eq_data.json'
# with open(reader_file,'w') as f:
# json.dump(all_eq_data,f,indent=4)
all_eq_dicts = all_eq_data['features']
mags,titles,lons,lats = [],[],[],[]
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
title = eq_dict['properties']['title']
lon = eq_dict['geometry']['coordinates'][0]
lat = eq_dict['geometry']['coordinates'][1]
mags.append(mag)
titles.append(title)
lons.append(lon)
lats.append(lat)
print(mags[:10])
print(titles[:2])
print(lons[:5])
print(lats[:5])
绘制震级散点图
在确保显示的信息正确无误后,可以将注意力转向样式和外观:
import json
import plotly.express as px
# 探索数据的结构。
filename = './eq_data_1_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
# reader_file = 'readable_eq_data.json'
# with open(reader_file,'w') as f:
# json.dump(all_eq_data,f,indent=4)
all_eq_dicts = all_eq_data['features']
mags,titles,lons,lats = [],[],[],[]
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
title = eq_dict['properties']['title']
lon = eq_dict['geometry']['coordinates'][0]
lat = eq_dict['geometry']['coordinates'][1]
mags.append(mag)
titles.append(title)
lons.append(lon)
lats.append(lat)
fig = px.scatter(
x=lons,
y=lats,
labels= {'x':'经度','y':'纬度'},
range_x=[-200,200],
range_y=[-90,90],
width=800,
height=800,
title='全球地震散点图',
)
fig.write_html('global_earthquakes.html')
fig.show()
Plotly Express 是Plotly 的高级接口。语法与Matplotlib类似。
fig.write_html方法可以将可视化图保存为html文件,在文件夹中找到global_earthquakes.html文件,用浏览器打开即可。
如果使用Jupyter Notebook,可以直接使用fig.show方法在notebook单元格显示散点图。
另一种指定图表数据的方式
当前,经纬度数据是手动配置的:
--skip--
x=lons,
y=lats,
labels= {'x':'经度','y':'纬度'},
这是在Plotly Express中给图表定义数据的最简单方式之一,但在数据处理中并不是最佳的。
下面是另一种给图表定义数据的等效方式,需要使用pandas数据分析工具,首先创建一个DateFrame,将需要的数据封装起来:
import json
import pandas as pd
import plotly.express as px
# 探索数据的结构。
filename = './eq_data_1_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
# reader_file = 'readable_eq_data.json'
# with open(reader_file,'w') as f:
# json.dump(all_eq_data,f,indent=4)
all_eq_dicts = all_eq_data['features']
mags,titles,lons,lats = [],[],[],[]
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
title = eq_dict['properties']['title']
lon = eq_dict['geometry']['coordinates'][0]
lat = eq_dict['geometry']['coordinates'][1]
mags.append(mag)
titles.append(title)
lons.append(lon)
lats.append(lat)
data = pd.DataFrame(
data=zip(lons,lats,titles,mags),columns=['经度','纬度','位置','震级']
)
data.head()
fig = px.scatter(
data,
x='经度',
y='纬度',
labels= {'x':'经度','y':'纬度'},
range_x=[-200,200],
range_y=[-90,90],
width=800,
height=800,
title='全球地震散点图',
)
fig.write_html('global_earthquakes.html')
fig.show()
在这种方式中,所有有关数据的信息都以键值对的形式放在一个字典中。相比于前一种格式,这种格式让我们能够无缝衔接数据分析,并且更轻松的进行定制。
定制标记的尺寸
确定如何改进散点图的样式时,应着重于让要传达的信息更清晰,当前的散点图显示了每次地震的位置,但没有指出震级,我们让观察者迅速获悉最严重的地震发生在什么地方。
import json
import pandas as pd
import plotly.express as px
# 探索数据的结构。
filename = './eq_data_1_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
# reader_file = 'readable_eq_data.json'
# with open(reader_file,'w') as f:
# json.dump(all_eq_data,f,indent=4)
all_eq_dicts = all_eq_data['features']
mags,titles,lons,lats = [],[],[],[]
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
title = eq_dict['properties']['title']
lon = eq_dict['geometry']['coordinates'][0]
lat = eq_dict['geometry']['coordinates'][1]
mags.append(mag)
titles.append(title)
lons.append(lon)
lats.append(lat)
data = pd.DataFrame(
data=zip(lons,lats,titles,mags),columns=['经度','纬度','位置','震级']
)
data.head()
fig = px.scatter(
data,
x='经度',
y='纬度',
range_x=[-200,200],
range_y=[-90,90],
width=800,
height=800,
title='全球地震散点图',
size='震级',
size_max=10,
)
fig.write_html('global_earthquakes.html')
fig.show()
Plotly Express支持对数据系列进行定制,这些定制都以参数表示,这里使用了size参数来指定散点图中每个标记的尺寸,我们只需要将前面data中的'震级'字段提供给size参数即可,另外,标记尺寸默认为20像素,还可以通过size_max=10将最大显示尺寸缩放到10.
定制标记的颜色
还可以定制标记的颜色,以呈现地震的严重程度。
import json
import pandas as pd
import plotly.express as px
# 探索数据的结构。
filename = './eq_data_30_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
# reader_file = 'readable_eq_data.json'
# with open(reader_file,'w') as f:
# json.dump(all_eq_data,f,indent=4)
all_eq_dicts = all_eq_data['features']
mags,titles,lons,lats = [],[],[],[]
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
title = eq_dict['properties']['title']
lon = eq_dict['geometry']['coordinates'][0]
lat = eq_dict['geometry']['coordinates'][1]
mags.append(mag)
titles.append(title)
lons.append(lon)
lats.append(lat)
data = pd.DataFrame(
data=zip(lons,lats,titles,mags),columns=['经度','纬度','位置','震级']
)
data.head()
fig = px.scatter(
data,
x='经度',
y='纬度',
range_x=[-200,200],
range_y=[-90,90],
width=800,
height=800,
title='全球地震散点图',
size='震级',
size_max=10,
color='震级'
)
fig.write_html('global_earthquakes.html')
fig.show()
默认的实觉映射的图例渐变色范围是从蓝到红再到黄,数值越小则标记越蓝,而数值越大则标记越黄。
其他渐变
Plotly Express有大量渐变可供选择。要获悉有哪些渐变可供使用。
import plotly.express as px
for key in px.colors.named_colorscales():
print(key)
这些渐变其实映射到一个个配色列表,使用px.colors.driverging.RdY1Gn[::1]可以将对应颜色的配色列表反转。
添加鼠标指向时显示的文本
import json
import pandas as pd
import plotly.express as px
# 探索数据的结构。
filename = './eq_data_30_day_m1.json'
with open(filename) as f:
all_eq_data = json.load(f)
# reader_file = 'readable_eq_data.json'
# with open(reader_file,'w') as f:
# json.dump(all_eq_data,f,indent=4)
all_eq_dicts = all_eq_data['features']
mags,titles,lons,lats = [],[],[],[]
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
title = eq_dict['properties']['title']
lon = eq_dict['geometry']['coordinates'][0]
lat = eq_dict['geometry']['coordinates'][1]
mags.append(mag)
titles.append(title)
lons.append(lon)
lats.append(lat)
data = pd.DataFrame(
data=zip(lons,lats,titles,mags),columns=['经度','纬度','位置','震级']
)
data.head()
fig = px.scatter(
data,
x='经度',
y='纬度',
range_x=[-200,200],
range_y=[-90,90],
width=800,
height=800,
title='全球地震散点图',
size='震级',
size_max=10,
color='震级',
hover_name='位置',
)
fig.write_html('global_earthquakes.html')
fig.show()
小结
学习了如何使用现实世界中的数据集,如何处理CSV和JSON文件。
。。。
叨叨几句... NOTHING