四、 实战练习
一、维基解密阿富汗战争日志
我们从一些具体的案例来练习数据新闻的制作流程。第一个案例来自于《卫报》关于维基解密阿富汗战争日志的报道。维基解密向《卫报》提供了阿富汗战争日志数据、伊拉克战争日志数据和美国大使馆密电丑闻数据。这些数据均来自美国军方重大行动数据库(SIGACTS)。《卫报》的调查新闻报道团队对于这个数据感到抓狂,它共有92201行数据,对于习惯于处理小规模数据的人而言,这是一个不小的挑战。为了让专业的记者团队可以更好地挖掘数据提炼新闻选题,《卫报》还和《纽约时报》、《明镜周刊》共享了维基解密“阿富汗战争日志数据”,希望通过数据分析,全景展现战争的真实情况。
为了更好的检索数据,《卫报》的开发团队建设了一个简单的内部数据库,提供在线检索服务。这样,记者就可以根据关键词和事件主题在数据库中进行搜索。为了系统地分析这些数据,开发团队还进行了大量的数据清洗,优化数据结构,将每个事件从时间、日期、概述、伤亡人数、经纬度等变量进行描述。
从2004年到2009年,阿富汗战争期间发生了大量的爆炸和伏击事件。维基解密数据记录了7500条临时爆炸装置(Improvised Explosive Device, IED)爆炸或伏击事件,另外还有8000个发现炸弹后拆弹的记录。根据这些数据,《卫报》做了题为“近六年发生的临时爆炸装置袭击”的数据新闻报道,试图去分析这些爆炸有什么变化、相互之间有什么区别,并分享了这部分临时爆炸装置袭击数据, 。我们使用这些公开的数据,来复现《卫报》的数据分析。
我们主张采用开源的编程工具(比如python)来完成数据获取、清洗、分析和初步的可视化,互动可视化可以采用ECharts或D3.js来完成,信息图和其它平面设计则可以通过Adobe illustrator等工具来完成。其中,Python是一个非常好的数据科学编程工具,伴随着数据科学和深度学习技术的普及,Python社区不断发展。Python是一种面向对象的、解释型的程序设计脚本语言。它的语法简洁而清晰,具有非常强大的标准库和丰富的第三方模块,是TIOBE编程语言排行榜中的“2010年度编程语言”。2017年2月,python正式迁移到GitHub维护,成为2017年最流行编程语言(2016年排名第三),在2017年8月数据挖掘资讯网站KDnuggets做的一项调查显示Python超过R,成为数据科学和机器学习最常用语言。
采用Anaconda可以非常方便地安装Python软件,推荐安装3.0以上版本。Anaconda集成了jupyter notebook、numpy、scipy、pandas、sklearn等众多的工具。其中jupyter notebook使得用户可以在网页端互动式地编写Python语言,运行结果会被很好地保存下来,便于理解、交流和传播,提高了编程的可复制性。安装anaconda后,打开电脑的终端,输入jupyter notebook,就会进入到jupyter notebook的编程界面。
首先,导入需要的工具包,包括matplotlib、seaborn、pandas。
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
然后,就可以读入数据。我们使用Pandas来读入ExplodedIED.xls这个Excel数据。原始数据可以从《卫报》下载;为方便使用,大家可以直接从下面代码中给出的百度盘下载。我将数据和jupyter notebook文件放在同一个路电脑文件夹中,就不需要再指明文件在具体的哪一个路径下面。我们使用pandas中的read_excel命令就可以很好地读入数据。读入数据后,就可以使用head命令来查看数据的样式。使用len命令可以很方便地查看数据的行数(7527)。
# download the data from https://pan.baidu.com/s/1jKjBXOy
df = pd.read_excel('ExplodedIED.xls')
df.head()
len(df)
df.columns
使用columns命令,就可以查看所有的列的名字(变量名)。包括以下各列:’ReportKey’, ‘DateOccurred’, ‘Type’, ‘Category’, ‘TrackingNumber’, ‘Title’, ‘Summary’, ‘Region’, ‘AttackOn’, ‘ComplexAttack’, ‘ReportingUnit’, ‘UnitName’, ‘TypeOfUnit’, ‘FriendlyWIA’, ‘FriendlyKIA’, ‘HostNationWIA’, ‘HostNationKIA’, ‘CivilianWIA’, ‘CivilianKIA’, ‘EnemyWIA’, ‘EnemyKIA’, ‘EnemyDetained’, ‘MGRS’, ‘Latitude’, ‘Longitude’, ‘OriginatorGroup’, ‘UpdatedByGroup’, ‘CCIR’, ‘Sigact’, ‘Affiliation’, ‘DColor’。
接下来就进入到数据清洗的环节。我们可以看到DateOccurred代表袭击事件发生的时间,包括了年月日小时分钟秒的信息,比如“2004-01-06 00:00:00”。我们在统计事件发生的时间的时候,只需要月份级别的时间颗粒度就可以了。因此,我们构造了一个新的变量叫做time, time的每个元素来自于DateOccurred,但是只取其年份和月份的信息,日期的信息统一修改为“01”。另外,需要注意的是,这个数据里的时间有少量的错误,我们将其替换为缺失值。此处的缺失值使用numpy库中的nan命令来表示。最后,我们需要使用pandas中的to_datetime命令将time由字符串格式更改为日期格式。类似的逻辑,我们可以构造一个名为year的变量,用来表示袭击事件是在哪一年发生的。
df['time'] = [str(i)[:8]+'01' for i in df.DateOccurred]
df['time'] = [i if '200' in i else np.nan for i in df.time ]
df['time'] = pd.to_datetime(df.time, format = '%Y-%m-%d')
df['year'] = [str(i)[:4] for i in df.DateOccurred]
df['year'] = [int(i) if '200' in i else np.nan for i in df.year]
df = df.dropna(subset = ['Latitude','Longitude'])
接下来,就可以对数据进行分析和可视化。我们从分析袭击事件发生的地点开始。在df数据集当中,Region表示事件发生的方位,共南部(SOUTH)、东部(EAST)、北部(NORTH)、西部(WEST)、首都(CAPITAL)和未知(UNKNOWN)六种情况,使用pandas中的value_count可以计算每一个方位有多少袭击事件。具体命令为:df.Region.value_counts()。结果表明南部地区(N = 3644)和东部(N = 2869)地区最多,其它地区较少,西部、北部、首都地区各有356、253、215件袭击事件,此外还有9个缺失地区信息的袭击事件。我们也如同卫报一样采用饼状图对事件进行可视化。Pandas基于matplotlib提供了更加定制化的可视化功能。
plt.figure(figsize = (8, 8))
explode = (0.1, 0.1, 0.2, 0.1, 0.2, 0.3)
df.Region.value_counts().plot(kind='pie', explode = explode,
autopct='%0.1f%%',
pctdistance=0.5, shadow=True)
plt.show()
其中,matplotlib.pyplot为python数据可视化提供了最为基础的工具。例如,通过figure函数可以定义所绘制图形的基本属性,例如图片的大小在这个例子里被指定为figsize = (5, 5)。我们将df.Region.value_counts()所输出的结果采用plot函数绘制出来,指定图片的类型(kind)为饼状图(pie)。设置饼状图每个部分偏离圆心的比例(explode)分别为0.1、0.1、0.2、0.1、0.2、0.3;设置每一个部分的比例(autopct)精确到小数点后1位数;设置每部分比例的文字距离圆心的位置(pctdistance)在半径的0.5处;此外还可使指定绘制出来每一个部分的阴影(shadow)。
图7-11 阿富汗战争中袭击事件所在区域的饼状图
在阿富汗战争IED袭击数据中另外一个非常值得挖掘的信息是爆炸和袭击事件随着时间的变化。如同统计事件发生地区的数量一样,此处我们依然使用value_count命令来对df.time变量进行处理;然后,使用plot命令就绘制出来。当然了,这里我们需要把图表类型设置为线型图(kind = ‘line’)。我们从数据中可以发现在2009年8月,袭击事件的数量最多,这是以为2009年8月20日是阿富汗总统选举,因此其前后的袭击事件最多。我们需要使用idxmax命令来提取df.time.value_counts()取值为最大值ymax时的x轴取值xmax。然后,就可以使用matplotlib中的vlines函数来绘制一条红色的线来标示出袭击事件最多的时间。我们进一步使用matplotlib中的annotate来注释一下导致这一个峰值的原因为8月的阿富汗总统选举,见图7-12。
df.time.value_counts().plot(kind = 'line', figsize = (15, 5))
xmax = df.time.value_counts().idxmax()
ymax = df.time.value_counts().max()
plt.vlines(x=xmax, ymin = 0, ymax = ymax, color='r')
plt.annotate('The presidential election \n 2018 Aug 20',
xytext=(pd.Timestamp('2007-06-01 00:00:00'), ymax),
xy=(xmax, ymax),
arrowprops=dict(facecolor='green', shrink=0.05),
fontsize = 20)
plt.show()
图7-12 阿富汗战争中袭击事件的时间序列图
对于袭击事件发生地区的分析告诉我们空间分布的不均匀性,对于袭击事件的时间序列分析同样揭示了在时间上同样存在不均匀的特性。接下来我们就尝试将每一年的袭击事件通过地图的形式进行更为具体的分析。我们将使用到的一个主要的工具是geopandas。这个工具需要通过pip install geopandas代码在电脑终端中进行安装。
我们绘制袭击事件发生地点的基本逻辑如下:首先,我们需要阿富汗这个国家的形状数据country来作为绘图的背景;然后,我们需要袭击事件发生地点数据places。最后,将袭击地点places覆盖到国家背景上去就可以得到需要的可视化效果。
我们从人类冲突实证研究项目网站(The Empirical Studies of Conflict Project, ESOC)下载所需要的阿富汗国家形状文件(shapefile)。此处,使用的是阿富汗398个区的形状文件。然后,就可以通过geopandas的GeoDataFrame下的子命令from_file来读取这个形状数据,将其命名为country。类似于pandas集成了matplotlib的绘图功能,geopandas同样做了类似的优化,因此使用geopandas绘图同样非常简单,只需要使用plot函数就可以根据country绘制出国家背景图片,如图7-13所示。
# Read file using gpd.read_file()
import geopandas as gpd
country = gpd.GeoDataFrame.from_file('afghanistan_district398.shp')
country.plot(figsize = (15, 15), color = 'grey')
plt.show()
图7-13 阿富汗国家398个区的可视化
from shapely.geometry import Point
import geopandas as gpd
# you need to install geopandas first!
def plot_points_on_shapefile(year, ax):
country = gpd.GeoDataFrame.from_file('afghanistan_district398.shp')
# Create a DataFrame with some cities, including their location
places = df[['TrackingNumber', 'Latitude', 'Longitude', 'year']][df.year == year]
# Create the geometry column from the coordinates
# Remember that longitude is east-west (i.e. X) and latitude is north-south (i.e. Y)
places["geometry"] = places.apply(lambda row: Point(row["Longitude"], row["Latitude"]), axis=1)
del(places["Latitude"], places["Longitude"], places["year"] )
# Convert to a GeoDataFrame
places = gpd.GeoDataFrame(places, geometry="geometry")
## Declare the coordinate system for the places GeoDataFrame
# GeoPandas doesn't do any transformations automatically
# CRS (WGS84) transformation is needed.
places.crs = {"init": "epsg:4326"}
country.crs = {"init": "epsg:4326"}
## Perform the spatial join
country.plot(ax=ax, color="#cccccc")
places.plot(ax=ax, markersize=5, color="#cc0000")
plt.axis('off')
plt.title(str(year))
接下来,我们将按年提取每一年所需用到的经纬度数据为places。然后在places这个数据框中增加米归纳为geometry的一列数据,它的取值形式为POINT (64.46125793 32.41791916),其中POINT表示这是这是空间中的一个点,64.46125793为维度,32.41791916为经度。为了要得到这样格式的一列数,我们需要用到shapely工具包中的子命令Point,同时也用到了apply语句和lambda语句。构造出需要的变量geometry之后,就可以使用del命令来删除places当中的其它不需要的列。接着,需要使用geopandas中的GeoDataFrame来将places从普通的pandas数据框编程geopandas下的地理位置数据框。
此时,我们已经有了国家地理形状数据country和袭击事件地理位置数据places,在我们绘图之前,我们还需要确保它们使用的是同一个参考系。默认的参考系为WGS84, 我们这里采用crs命令为country和places指定采用epsg:4326这样一种投影方式。
然后,把这两个数据画在一起(使用同一个ax)就可以了。为了更简洁明了,我们使用plt.axis(‘off’)命令来去掉坐标轴,使用plt.title命令来加上图片标题。因为我们有六年的数据需要画,为避免重复,需要将以上代码写成一个简单的函数,即为plot_points_on_shapefile。这个函数需要输入两个参数,分别是年份year和子图ax。最后,我们调用这个函数,写一个简单的for循环,就可以把2004到2009年的图片画在一起,如图7-14所示。
fig = plt.figure(figsize=(12, 8),facecolor='white')
year = [2004+i for i in range(6)]
for k, i in enumerate(year):
ax = fig.add_subplot(2,3,k+1)
plot_points_on_shapefile(i, ax)
plt.tight_layout()
图7-14 阿富汗战争爆炸袭击事件的时空特征
同样可以采用Python来绘制基于网页的地理空间可视化展示。我们需要使用到一个叫做folium的第三方包。使用pip install folium即可在电脑终端安装好folium。我们首先调用folium及其插件plugins。这些插件中一个非常好的应用为热力图HeatMap,顾名思义,它可以帮助我们绘制袭击事件地点分布的热力图。
首先,我们需要使用for循环构造一个名为nodes的列表,列表中的每一个元素是一个元组,每一个元组由经度和维度两个数值组成。
其次,就可以使用folium的Map函数将阿富汗地理位置作为背景绘制出来。大需要输入一个经纬度坐标locatio,我们采用数据df中经度的均值和维度的均值作为location,我们选择使用’cartodbpositron’作为底图风格,选择初始状态的缩放比例为5.4。图片绘制出来之后,读者可以自己选择自己喜欢的缩放。
然后,使用add_child命令加入热力图数据信息;而热力图数据来自于HeatMap这个插件对于经纬度数据nodes处理的结果。
最后,使用fit_bounds和get_bounds来根据袭击事件地理位置信息选择一个最优的缩放。
这样就可以得到一个袭击事件地理位置分布的热力图。可以将这个热力图通过save命令保存为一个网页文件,或者直接在jupyter notebook中展示出来,如图7-15所示。
import folium
from folium import plugins
print(folium.__file__)
print(folium.__version__)
nodes = [(df.Latitude[i], df.Longitude[i]) for i in df.index]
map_osm = folium.Map(
location=[df.Latitude.mean(), df.Longitude.mean() ],
tiles = 'cartodbpositron',
zoom_start=5.4)
map_osm.add_child(plugins.HeatMap(nodes))
map_osm.fit_bounds(map_osm.get_bounds())
map_osm.save('heatmap.html')
map_osm
当然了,也可以使用folium将所有袭击事件的地点逐年绘制出来,并保存为网页文件。此处不再赘述。以上分析所使用到的所有数据、代码、可视化结果都可以通过Github网站获取。
图7-15 阿富汗战争爆炸袭击事件的热力图
二、奥运会数据分析和ECharts的使用
我们将通过第二个实战练习来学习制作一个关于奥运会的数据新闻,并简要介绍ECharts的使用。在奥运赛场上,总有些国家长踞固定项目的榜首,在自己的传统强势项目上持续发光发热。早在1992年巴塞罗那奥运会,囊括了当时几乎所有的NBA顶尖选手的美国男篮表现得如梦如幻,被人们冠以“梦之队”的称号。之后这一说法渐渐流行起来,那些在单项上的地位长期无法为其他国家所撼动的实力无人能比的队伍也开始被称赞为“梦之队”,其中最常见的除了美国篮球,还有中国乒乓球队、中国跳水队和韩国射箭队。“梦之队”们凭借着自身的强势,成为各自项目的霸主对该项目进行着不同时间段的“统治”,也就是实现了对一些奥运项目的垄断。然而奥运中的这些垄断现象并不仅仅与体育运动项目本身相关,还与国家的实力相关,在更大程度上奥运会是大国“秀肌肉”的舞台。
回答以上所有问题的根本依然在于高质量的数据和计算。我们将采用《卫报》数据博客在机器学习比赛网站Kaggle上发布的奥运会数据,大家可以在Kaggle下载这个数据。这个数据记录了1896到2014年间奥林比赛运动的获奖情况,包括了三个数据文件,分别为dictionary.csv、summer.csv、winter.csv。其中,dictionary.csv为国家数据,包括国家名字、代码、人口、人均GDP四列;summer.csv和winter.csv分别是夏季奥运会和冬季奥运会的数据。我们主要分析夏季奥运会,在summer.csv数据中包括年份(Year),城市(City),运动类型(Sport),比赛领域(Discipline),运动员姓名(Athlete),国家(Country),性别(Gender),比赛事件(Event),奖牌类型(Medal)这些信息。
我们首先使用pandas的read_csv命令读入两个比赛数据和国家数据,分别命名为game和country。
%matplotlib inline
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Data https://www.kaggle.com/the-guardian/olympic-games
game = pd.read_csv('summer.csv')
country = pd.read_csv('dictionary.csv')
然后,就可以对各国在某一个比赛事件(Event)中的奖牌数。我们希望统计金、银、铜三种奖牌数量。并根据不同的奖牌给性,给这个国家一个比赛分数,比如一个简单的方法是铜牌是1分,银牌是2分,金牌是4分。我们采用以下代码来实现这样一个过程,初始阶段让gold、silver、bronze、score都为0,然后依据其得奖类型和数量赋值。
game['gold']=0
game['silver']=0
game['bronze']=0
game['score']=0
game['gold'][game['Medal']=='Gold'] = 1
game['silver'][game['Medal']=='Silver'] = 1
game['bronze'][game['Medal']=='Bronze'] = 1
game['score'][game['Medal']=='Gold'] = 4
game['score'][game['Medal']=='Silver'] = 2
game['score'][game['Medal']=='Bronze'] = 1
这样,我们就可以统计各国获得的金银铜三种奖牌的数量以及总的分数。实现这一步需要使用pandas中的groupby命令,接着对汇总后的数据按照得分score进行降序排列,并查看前二十名。分别为美国、苏联、英国、意大利、法国、德国、匈牙利、澳大利亚、瑞典、东德、中国、荷兰、俄罗斯、日本、挪威、加拿大、罗马尼亚、韩国、丹麦、西德。
gsb = game.groupby(['Country']).sum()[['gold', 'silver', 'bronze', 'score']]
gsb = gsb.sort_values(['score'], ascending = False)
gsb[:20]
衡量一个领域的竞争状况的基本方法是看各个国家在这个领域的累积奖牌数或者得分是否均匀,一种常用的被垄断程度的测量是基尼系数。基尼系数越大,表示不平等程度越高。基尼系数是根据洛伦兹曲线来定义的。洛伦兹曲线是为了研究国民收入分配问题提出的,将所有人按照贫困到富有进行从低到高排序,计算各个人口百分比所对应的收入百分比的曲线即为洛伦兹曲线。理想的情况是人口比例与财富比例完全相等,也就是一条从穿过原点、斜率是45度角的直线。理想情况和实际的洛伦兹曲线之间的差异所占的比例即为基尼系数。
def gini_coefficient(v):
bins = np.linspace(0., 100., 11)
total = float(np.sum(v))
yvals = []
for b in bins:
bin_vals = v[v <= np.percentile(v, b)]
bin_fraction = (np.sum(bin_vals) / total) * 100.0
yvals.append(bin_fraction)
# perfect equality area
pe_area = np.trapz(bins, x=bins)
# lorenz area
lorenz_area = np.trapz(yvals, x=bins)
gini_val = (pe_area - lorenz_area) / float(pe_area)
return bins, yvals, gini_val
按照基尼系数的定义,就可以定义一个名为gini_coefficient的函数,这个函数输入参数就是各个国家的奖牌数或者得分v。首先,使用numpy的函数linspace构造从0到100的11个分位数bins。总奖牌数或者总分数total,将v的各个取值使用sum命令累加起来就可以获得。然后,即可以计算11个分位数各自对应的纵轴取值的概率,记为yvals。此时,使用numpy中的trapz命令就可以得到理想直线所覆盖的面积pe_area以及洛伦兹曲线下的面积lorenz_area,也就可以计算出基尼系数。
我们将各国的总分数计算出来,调用定义好的gini_coefficient函数,就可以计算出来基尼系数为0.794,这意味着整个奥运会比赛被垄断的情况非常严重。为了更好展示这样一个计算过程,我们将理想直线和洛伦兹曲线绘制出来。
score_all = game.groupby(['Country']).sum()['score']
bins, result, gini_val = gini_coefficient(score_all)
plt.plot(bins, result, label="$observed$")
plt.plot(bins, bins, '--', label="$perfect\; eq.$")
plt.xlabel("$Fraction\; of\; Countries$")
plt.ylabel("$Fraction\; of \;Olympic Score$")
plt.title("$GINI: %.4f$" %(gini_val))
plt.legend(loc=0)
plt.show()
图7-16奥运会比赛的基尼系数
更有意思的是,我们可以计算每一年奥运会比赛各国得分的基尼系数,这样就可以分析随着时间变化奥运会被垄断情况是如何变化的。首先,按年和国家对得分进行汇总;然后对每一年各国得分计算一个基尼系数;最后,将每年的基尼系数和年份绘制出来就得到一条时间序列。结果显示初始二十年里基尼系数变化剧烈,非常不稳定。例如,第一届奥运会比赛的基尼系数较低,之后两届基尼系数非常高。到了1920年之后,每一年的基尼系数就相对稳定,随着时间变化稳定上涨。到了1980年之后,基本稳定在0.7左右。我们可以认为现在的奥运会比赛已经进入到了一个成熟期,虽然垄断程度较高,但这种垄断相对非常稳定。
ggy = game.groupby(['Year', 'Country']).sum()['score']
years = game.Year.unique()
gini = [gini_coefficient(ggy[i])[2] for i in years]
fig = plt.figure(figsize=(12, 4),facecolor='white')
plt.plot(years, gini, 'r-o')
plt.ylabel(r'$Gini\; Coefficients$', fontsize = 20)
plt.show()
图7-17奥运会比赛被垄断程度随时间的变化
除了以上内容之外,针对奥运会数据还可以分析很多有趣的话题,比如在单项比赛项目上的垄断情况,可以尝试找到那些领域的霸主。此外,可以看霸主的更迭如何发生。最后,还可以看在奥运会上的地位与国家实力(人口、人均GDP等)的关系。对于经过数据分析得到的可视化结果可以采用ECharts或D3等javascript工具进行可视化。其中,ECharts的使用比较简单。在ECharts官方网站上提供了一个五分钟上手ECharts的例子,将制作ECharts图表分为简单的三步:
第一步,下载ECharts,在官方网站下载即可。
第二步,新建一个html文件,使用script标签引入ECharts。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- 引入 ECharts 文件 -->
<script src="echarts.min.js"></script>
</head>
</html>
第三步,绘制图表。
首先,需要在body中建立一个文档对象模型(DOM)的容器,可以通过div标签增加一个id为“main”(或者其它名字)的容器,指定它的宽度和高度。例如:
<body>
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="main" style="width: 600px;height:400px;"></div>
</body>
然后,基于准备好的DOM,初始化ECharts实例,指定图表的配置项和数据,并使用指定的配置和数据显示图表就可以了。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ECharts</title>
<!-- 引入 echarts.js -->
<script src="echarts.min.js"></script>
</head>
<body>
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option = {
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
legend: {
data:['销量']
},
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>
在http://echarts.baidu.com/examples/这里提供了大量的官方例子,每个例子都给出了option的内容。当我们作图的时候,只需要对option进行简单修改就可以了。例如http://echarts.baidu.com/examples/editor.html?c=line-simple 给出的是绘制简单直线的方法。想要可以得到奥运会得分基尼系数随时间变化的曲线,只需要在这个页面左方的option部分进行以下操作:
- 将X轴的日期替换为奥运会的年份数据。
- 将Y轴的数值数据替换为每一年的基尼系数。
- 点击这个页面右下方的Download按钮,就可以将生成的html文件下载下来。
图7-18 ECharts图表制作
Python Script
http://nbviewer.jupyter.org/github/data-journalism/olympic/blob/gh-pages/olympic_games.ipynb
HTML Version
https://data-journalism.github.io/olympic/