上周果说组织了一次线下研讨沙龙,主要讨论了数据获取、分析与表达,这里将分三次在果说微信中与大家分享相关内容,虽然技术性强点,但对于高年级本科生,研究生应该还是有些价值的。
毕竟上周刚开的苹果WWDC14上也说么:Write the code, Change the world.
这一篇主要讲涉及到数据获取、分析和表达的目标,工具(及学习材料),和简单方法,后两篇会有比较多的例子。首先,让我们从三个词开始:
技术、问题与系统 —— 写在前面
技术(Technique)
研究时间越长,技术占的重要性越低。我的理解是这样:随着研究的进行,研究者可以学会更多的技术,当你掌握了一项技术后,它就变成了一个工具,对于研究来说,技术的重要性体现在“工具”层面。
但是前提是要“掌握技术”,而且技术(相对于问题和系统)比较好教,好学,好分享。
问题(Question)
研究领域的选择,未来方向的确定,是提问题提出来的。但提问题不是随随便便的问题,而是要想Big Question。
Perhaps the most important single step in the research process is choosing a question to investigate. What most distinguishes scientists noted by posterity is not their technical skill, but they chose interesting problems. — Tim Hunt. 2011
系统(System)
一个人永远学不完新东西,所以更重要的是要有自己的研究体系,如果没有自己的研究体系,只能要么看别人做什么跟着做什么,或者自己会什么就做什么,东打一枪、西放一炮,很难有系统发现。对于体系的培养,施老师觉得学习本学科领域的科学史(不是泛的科学史)非常重要,看科学发展的过程,会让人对所在领域有个 全局观,能培养一种思维方式。
——上述三点来自施一公老师的报告,后面的内容笔者会针对以上每个要点进行引申与理解。
1.1 目标 | Target
Step1 一个想要研究的问题 -> Step2 将问题抽象成可以科学研究的对象 -> Step3 找对应数据 -> Step4 分析 -> Step5 返回问题
前两步非常非常重要,但对不同个体,不同研究方向差异很大,所以我们在这里重点关注Step3 Step4。
如果非常认真,一到两个学期(6-12个月,500-1000小时,按大学一门3学分的课是100小时左右的话,相当于5-10门三学分的课),可以掌握用于自身研究的最基本技能。
1.2 软件及相关资料 | Python & R
Software:
对数据处理、画图有比较多需求的同学可以学R,对应的软件是Canopy(Python的集成开发环境);对计算机仿真、互联网数据抓取、机器学习有比较多需求的同学可以试试Python,对应的开发软件是RStuidio(R的集成开发环境)
Packages:
开源软件的好处就是可以有不同的人贡献各种“包”,极大方便我们的生活。与本节讨论内容相关的包:Python (Beautiful Soup, csv, urllib2, json); R (ggplot2, ggmap, maps[内置了一些地图,但无中国], mapdata[有中国地图,但比较老,重庆和四川还没有分开])
Books:
-
Learn Python the Hard Way (作者提供免费版)
-
《用Python做科学计算》(HYRY Studio,与数值分析、模拟有关)
-
R in Action (R的入门读物)
-
Visualize This (教很多可视化的操作)
-
数学之美 (数学及模型思想)
MOOC(在线课程):
Coursera
Data Science[基于R语言的系列课程,约翰霍普金斯大学]一共有九门课,其中1,2,3,4,6,7都比较适合看:
-
The Data Scientist’s Toolbox
-
R Programming
-
Getting and Cleaning Data
-
Exploratory Data Analysis
-
Reproducible Research
-
Statistical Inference
-
Regression Models
-
Practical Machine Learning
-
Developing Data Products.
Model Thinking[用模型思考问题,密歇根大学]
Maps and Geospatial Revolution[简单的地理学介绍及其于ESRI在线平台的地图制作,PennState]
1.3 过程 | Process:
如何找数据? | Where’s the data?
-
公开数据集(中国的数据可以在这里找到:知网、新浪爱问、人大经济论坛、政府公开数据网站:http://data.stats.gov.cn/、Beijing City Lab 等)
-
申请政务公开(统计局网站有联系方式,可查经普、人口普查、统计年鉴等)
-
互联网数据抓取(意识到有系统误差的存在,这是由抽样方式造成的,比如微博数据只是针对使用微博的用户)
互联网数据抓取过程,以地理信息为例:
-
geocoding
-
web crawling
-
data clean (structured data vs. unstructured data)
-
analysis
-
visualize
geocoding-api
Geocoding API包括地址解析和逆地址解析功能。
http://developer.baidu.com/map/geocoding-api.htm
地址解析是指,根据地址获取坐标。例如:“北京市海淀区中关村南大街27号”地址解析的结果是“lng:116.31985,lat:39.959836”。
http://api.map.baidu.com/geocoder?address=地址&output=输出格式类型&key=用户密钥&city=城市名
逆地址解析是指,根据坐标获取地址。例如:“lat:31.325152,lng:120.558957”逆地址解析的结果是“江苏省苏州市虎丘区塔园路318号”。
http://api.map.baidu.com/geocoder?location=纬度,经度&output=输出格式类型&key=用户密钥
我们在这里给出几个比较简单的例子,主要是基于R和相应的几个包。用到的工具介绍和学习资料请参考上一篇推送—数据的获取、分析与表达(1)。
1.4 Examples | 例子
Example 1:不需要编程的数据可视化表达
基础资料:
0)数据,因人而异;
1)矢量中国地图(搜索引擎很容易找到);
2)配色方案,可参考一个提供配色选择方案的网站ColorBrewer;
3)软件工具:AI(illustrator)
推荐经常看一看《经济学人》杂志和《纽约时报》的图表,我认为是所有出版物中做的比较好的。(比如http://www.economist.com/content/chinese_equivalents)
如何搞定中国的地图,请看:
《终于搞定了中国分省市地图》(http://yihui.name/cn/2007/09/china-map-at-province-level/)
《用R软件绘制中国分省市地图》(http://cos.name/2009/07/drawing-china-map-using-r/)
Example 2:坐标获取、距离测量和地图获取
R的一个软件包ggmap
(1)运用geocode功能获取经纬度坐标
输入
geocode("China")
返回
lon lat
1 104.1954 35.86166
即为中国的经纬度坐标。
(2)运用mapdist进行距离测量
输入
mapdist(‘Tsinghua University’, ‘Beijing University’, ‘walking’)
返回
from to m km miles seconds
1 Tsinghua University Beijing University 3329 3.329 2.068641 2458
minutes hours
1 40.96667 0.6827778
从清华到北大竟然3.3公理,要41分钟,估计是从东门算的吧。
(3)运用get_map获取地图
library(ggmap)
library(mapproj)
map <- get_map(location = ‘Beijing’, zoom = 8) #以北京为中心,zoom代表类似放大倍数.
京津冀地区出现了。GOOGLE地图本身就是个大的GIS系统,如果在上面一行代码里加上 maptype = ‘roadmap’就可以得到北京的路网图。
map <- get_map(location = ‘Beijing’, zoom = 10, maptype = ‘roadmap’) #北京路网
更重要的是基于GOOGLE地图我们可以叠加各种自己处理过的信息,比如很火的航班数据可视化,在Mapping the World’s Biggest Airlines里有详细描述,但不是基于GOOGLE地图。在中国国内航线信息的可视化中,有一个简化的作法。我也简单画了一个,有时间会再研究下那个比较FANCY的夜景航线图是怎么做出来的。
参考:http://donglei.name/2013/10/map-data-with-r/
Example 3:制作世界范围的数据表达图
需要在地图上表达《2008年联合国人类发展报告》中未成年人生育率按国家分布的情况(每1000名15-19岁女性中生育数量)。
library(maps) #载入maps
fertility <- read.csv("http://book.flowingdata.com/ch08/points/adol-fertility.csv")
map(‘world’, fill = FALSE, col = "#cccccc") #选择世界地图,不填充,底图为灰色
symbols(fertility$longitude, fertility$latitude,
circles = sqrt(fertility$ad_fert_rate), add = TRUE,
inches = 0.1, bg = "#93ceef", fg = "#ffffff") #圆圈的大小(面积而非半径)由生育率决定
即可得到如上所示的世界未成年人生育率按国家的分布情况图。
这次继续给出两个稍微复杂点的例子,后面我们还会推送一些作者总结的相关学习资源,还有关于GIS的相关文章,敬请期待。
Example 4: Beijing House Price
Step 1. Get Data (Python爬虫)
import urllib2 #Python中常用的爬取库
import time
link_start = ” #此处为解析到的爬取网站url
link_end = ” # 如需要原始url地址可以联系公共号
rawdata = ” #存取原始数据
#这一段代表要爬取的经纬度范围,及网格大小
lat = 39.55
for i in range(30):
print i
lat += 0.025
lng = 116.05
for j in range(35):
print j
lng += 0.025
#抓取相关内容
link = link_start + str(lat) + ‘,’ + str(lat+0.1) + ‘,’ + str(lng) + ‘,’ + str(lng+0.1) + link_end
time.sleep(3) #不要过于频繁,这里一次抓取尝试停顿3秒
response = urllib2.urlopen(link)
html = response.read()
#数据清理
index = html.find(‘],"props’)
if index > 10:
myItem = html[10:index] + ‘,’
print myItem
rawdata += myItem
target = open(‘center.txt’, ‘w’)
target.truncate()
target.write(rawdata)
target.close()
Step 2. Visualize (R的ggplot2)
library(ggplot2)
library(ggmap)
#读入文件
price <- read.csv("HousePrice2013.csv")
#将价格分组
price$ID <- (price$Price %/% 20000 + 1)
price$ID[price$ID > 5] <- 5
price$ID <- as.factor(price$ID)
#设置要画图的经纬度范围
price1 <- price[price$Lng < 116.8 & price$Lng > 116.0,]
price2 <- price1[price1$Lat < 40.2 & price1$Lat > 39.6,]
#用ggmap载入北京底图
map <- get_map(location = "beijing", zoom = 10, messaging = FALSE, color = "bw",maptype = ‘toner’, source="stamen")
g <- ggmap(map)
#画点,设置点的大小、透明度等
p <-g + geom_point(data=price2, aes(x=price2$Lng, y=price2$Lat, colour=price2$ID), size=3, alpha=0.5)
#设置颜色、图例等
p <- p + scale_colour_manual(name="House Price(RMB)",
values=c("#f1eef6", "#d7b5d8", "#df65b0", "#dd1c77", "#980043"),
labels=c("0-20,000","20,000-40,000","40,000-60,000","60,000-80,000", "80,000+"))
print(p)
Step 3. Analysis
根据不同分析问题进行具体分析。
Example 5: 美国失业率地图 (整理自Visualize This一书)
这是美国2010年8月失业情况按县域的分布,红色越深表示失业率越高,下次我记得加比例尺。数据可以在这里下载。和文章一开始提到的地图放到一个文件夹下。
这张图比前之前的复杂些,其于Python而不是R完成,思路就是找到地图中不同区域,然后让数据中表示的区域与地图表示的一一对就,再用失业率分成几种颜色向对应区域填充,主要分为三步:
1.载入数据和地图,这里SVG地图是矢量地图,可用文本编辑,这也是可用Python处理的基础。
2.用各自的“地址”对应区域,需要将失业率数据中的地址做些小处理以和SVG图中的匹配。
3.填充颜色,这组颜色由ColorBrewer生成,其实可以选择任何自己喜欢又能表达充分的色系。
# -*- coding: utf-8 -*-
import csv
from bs4 import BeautifulSoup #bs4之后导入的方法与书中的老版本不一样
# Read in unemployment rates
reader = csv.reader(open(‘unemployment-aug2010.txt’, ‘r’), delimiter=",") #文件名用数据的名字,如果直接下载,则为unemployment-aug2010.txt
# Load the SVG map
svg = open(‘counties.svg’, ‘r’).read() #文件名为SVG地图的名字
#SVG里每条路径都有唯一ID,正好是其所属州+所属县,失业数据里也有州和县的代码,不过是分开的。如,阿拉巴马州Autauga县的州码是01,县码是001,在SVG图中路径ID就是01001
unemployment = {}
rates_only = [] # To calculate quartiles
min_value = 100; max_value = 0; past_header = False
for row in reader:
if not past_header:
past_header = True
continue
try:
full_fips = row[1] + row[2]
#将州码和县码合成一个数字,在Python规则里数列从第0个开始,[1]代表数列里的第二个数
rate = float( row[5].strip() )
unemployment[full_fips] = rate
rates_only.append(rate)
except:
pass
# Load into Beautiful Soup
soup = BeautifulSoup(svg) #bs4不需要再定义空标签.构造方法的 selfClosingTags 参数已经不再使用.
# Find counties
paths = soup.findAll(‘path’)
# Map colors,Red-purple
colors = ["#F1EEF6", "#D4B9DA", "#C994C7", "#DF65B0", "#DD1C77", "#980043"]
# County style , fill在代码最后,值为空,由各县失业率来定
path_style = ‘font-size:12px;fill-rule:nonzero;stroke:#FFFFFF;stroke-opacity:1;stroke-width:0.1;stroke-miterlimit:4;stroke-dasharray:none;stroke-linecap:butt;marker-start:none;stroke-linejoin:bevel;fill:’
# Color the counties based on unemployment rate
for p in paths:
if p[‘id’] not in ["State_Lines", "separator"]:
# pass
try:
rate = unemployment[p[‘id’]]
except:
continue
# Linear scale
if rate > 10:
color_class = 5
elif rate > 8:
color_class = 4
elif rate > 6:
color_class = 3
elif rate > 4:
color_class = 2
elif rate > 2:
color_class = 1
else:
color_class = 0
color = colors[color_class]
p[‘style’] = path_style + color
print soup.prettify()
把上面的文件保存在与地图、失业率数据相同的文件夹下,然后在Terminal(Mac)中打开对应的存储路径,再输入:
python colorize_svg.py > us_unemployment_map.svg
怎么样,顺利完成后还是很开心的。SVG可以在illustrator中随意编辑,发挥去吧,少年:)
前面我们介绍了一些数据获取、分析与表达的方法,这里面的内容非常广阔,主页菌也只是了解一点点,更多的内容有待大家在实践中挖掘。作为这个系列的最后一篇,我们在这里说一下数据分析过程中可能需要注意的点,另外提供一些扩展阅读资源。
1.5 Tips | 一些可能需要注意的点:
Scale | 尺度问题:
不同的问题在不同尺度上分析,得到的结论可能是不同的。
Mapping Totals vs. Mapping Rates
注意在地图上要表达的是总量概念还是比率概念。总量概念往往有population dependence。(哪儿人多反应的现象总是多的。)
(例如,上面两个图分别是住房空置数量,和住房空置率,两张图反应的问题是很不相同的。Photo Credit: Anthony C. Robinson)
Correlation vs. Causation
相关和因果是两回事,相关并不代表因果,很有可能有“伪相关”变量的存在。
Population Dependence:
Cause maps of raw values to always highlight heavily populated places
编码问题
尽量用csv格式而不是xls, 另外,中文汉字可能存在编码问题,注意编码格式。
1.6 进一步学习 | Reference:
Data:
OpenStreetMap: http://www.openstreetmap.org/
哥伦比亚大学Socioeconomic data and applications center (SEDAC): http://sedac.ciesin.columbia.edu/data/sets/browse
国家统计局:http://www.stats.gov.cn/
香港数据: http://www.gov.hk/en/theme/psi/datasets/
United Nations http://data.un.org/
美国数据:http://www.data.gov/ http://www.census.gov/
芝加哥数据:http://thechangelog.com/the-city-of-chicago-is-on-github/
英国数据:http://data.gov.uk/
伦敦数据:http://data.london.gov.uk/
法国数据:http://data.gouv.fr/
德国数据:http://www.govdata.de/
澳大利亚数据:http://data.gov.au/
日本数据:http://www.data.go.jp/
Ghana: http://data.gov.gh
其它国家: http://www.data.gov/opendatasites
历史地理:复旦哈佛数据集(禹贡) http://www.fas.harvard.edu/~chgis/data/chgis/downloads/v4/datasets/index.html
人口面板数据:北大,西南财经的家庭跟踪调查数据
Collections by data scientists
Hilary Mason http://bitly.com/bundles/hmason/1
Peter Skomoroch https://delicious.com/pskomoroch/dataset
Jeff Hammerbacher http://www.quora.com/Jeff-Hammerbacher/Introduction-to-Data-Science-Data-Sets
Gregory Piatetsky-Shapiro http://www.kdnuggets.com/gps.html
http://blog.mortardata.com/post/67652898761/6-dataset-lists-curated-by-data-scientists
More specialized collections (http://jtleek.com/modules/03_GettingData/04_05_dataResources/#1)
Maps:
Spatial.ly http://spatial.ly/r/
http://axismaps.com/portfolio.php
http://www.qgis.org/en/site/
http://developers.cartodb.com/tutorials.html
Code:
http://www.pythonchallenge.com/
http://www.codecademy.com/tracks/python
原文始发于微信公众号(PPV课数据科学社区):【深度教程】数据的获取、分析与表达
原创文章,作者:ppvke,如若转载,请注明出处:http://www.ppvke.com/archives/30954