讲真,一开始让我写一篇这样的文章我是拒绝的,因为我以前总是觉得,学习是自己的事情,学到多少,学了什么,自己清楚就好。不过,在优达学城近两个月的学习之后,我逐步改变了观点,正如优达优等生互助班所倡导的“探索、自律、分享”的学习理念,实际上学习过程中的积累和分享的过程,也是提升学习兴趣的一个非常重要的点。所以,今天也想在这里汇总一下关于DAND课程里P3项目“整理 OpenStreetMap 数据”这阶段的学习总结,同时也记录一下自己的学习心路历程,这里特别感谢一下优等生互助班导师——鱼头同学的各种鼓励和支持@Clark Yu,非常负责任的一位导师,为了我们的学习进度也是操碎了心 /捂脸 应该说整个P3过程涉及的知识点还是比较多的,P3项目的要求是探索整理OpenStreetMap上的数据,并完成清洗、探索、分析的过程,这部分内容,应该是数据分析过程中一个相当耗时的部分,所以整个P3项目的预计完成时间还是比较长的。P3课程主要核心内容为:

数据分析提取

数据质量审查

清洗整理osm数据并使用SQL/MongoDB存储数据进行数据探索

数据分析提取

课程主要包含了使用Python从各个数据源分析提取数据的过程,处理的数据来源有CSV、Excel、JSON、XML以及HTML,这几类数据源都是比较常见的数据源,基本覆盖了我们常见的获取数据的途径,其中CSV、XML是格式比较标准且出现度非常高的两种文件格式,而JSON简洁和清晰的层次结构使得 JSON 成为一种理想的数据交换格式,它的键值对模式,非常类似Python中的字典,使用Python处理起来非常方便。

而对于HTML的数据提取,其实就是对网页上的内容进行的爬取和格式处理,课程里使用了Python中非常友好的BeatifulSoup库进行爬虫开发,非常容易的实现了对于网页内容的爬取。不过,鉴于课程的设计,关于爬虫的教学实际上并不是很深入,只是比较浅显的介绍了对于静态网页内容的爬取,在现在动态加载页面大行其道的今天,还是显得有点力不从心了,后续的实际过程中若数据来源比较多来自于HTML,那还是得深入对爬虫做一番了解。

Python读取各数据格式的API文档地址汇总:

CSV:

所用Python库:import csv

API文档: CSV File Reading and Writing - Python 2.7.13 documentation

Excel:

所用Python库:import xlrd

API文档: API Reference - xlrd 1.0.0 documentation

JSON:

所用Python库:import json

API文档: 18.2. json — JSON encoder and decoder

XML:

所用Python库:import xml

API文档: 19.8. xml.dom — The Document Object Model API

数据质量审查:

作为一个合格的DataAnalyst,自然要对所需进行探索分析的数据的质量有清晰的认识。对于数据质量的审查与清理是一个不断迭代的过程,数据质量在数据分析中的重要性毋庸置疑,数据的质量直接影响数据的产出和数据价值高低,而数据质量的基本要素则包含以下3个要素:

1、准确性

数据中记录的信息和数据是否准确,是否存在异常或者错误的信息。

导致一致性问题的原因可能是数据记录的规则不一,但不一定存在错误;而准确性关注的是数据记录中存在的错误,比如字符型数据的乱码现象也应该归到准确性的考核范畴,另外就是异常的数值,异常大或者异常小的数值,不符合有效性要求的数值,如访问量Visits一定是整数、年龄一般在1-100之间、转化率一定是介于0到1的值等。对数据准确性的审核有时会遇到困难,因为对于没有明显异常的错误值我们很难发现。

2、完整性

数据的记录和信息是否完整,是否存在缺失的情况。

数据的缺失主要有记录的缺失和记录中某个字段信息的缺失,两者都会造成统计结果的不准确,所以完整性是数据质量最基础的保障,而对完整性的评估相对比较容易。

3、一致性

数据的记录是否符合规范,是否与前后及其他数据集合保持统一。

数据的一致性主要包括数据记录的规范和数据逻辑的一致性。数据记录的规范主要是数据编码和格式的问题,比如网站的用户ID是15位的数字、商品ID是10位数字,商品包括20个类目、IP地址一定是用”.”分隔的4个0-255的数字组成,及一些定义的数据约束,比如完整性的非空约束、唯一值约束等;数据逻辑性主要是指标统计和计算的一致性,比如PV>=UV,新用户比例在0-1之间等。数据的一致性审核是数据质量审核中比较重要也是比较复杂的一块。

使用SQL/MongoDB存储数据并分析

课程里关于使用SQL还是MongoDB是需要学员根据自己的情况自行选择的,由于我工作中接触SQL比较多,所以这里我选择了MongoDB。

MongoDB 是一个基于分布式文件存储的数据库,他是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

MongoDB 3.4 中文文档 MongoDB - MongoDB Manual 3.4

MongoDB常用的操作:
MongoDB导入语句

使用Mongoimport命令,适用于已有文件导入

1
mongoimport -d dbname -c collectionname --file input-file.json

语句导入

1
db.cities.insert({"name" : "Chicago"})

1.查询
1.1 条件查询
1
db.cities.find(“name”: "Guangzhou", "class": "mid-size car")
1.2 投影查询
1
2
3
query = {“name”: "Guangzhou", "class": "mid-size car"}
projection = {"_id" : 0,"name" : 1}
db.cities.find(query, projection)
1.3 范围查询

运算符:

1
2
3
4
5
6
(>) 大于 - $gt
(<) 小于 - $lt
(>=) 大于等于 - $gte
(<= ) 小于等于 - $lte
$gt -------- greater than $gte --------- gt equal $lt -------- less than $lte --------- lt equal $ne ----------- not equalquery = {"foundingDate": {"$gte" : datetime(2000,1,1)}}
db.cities.find(query)

1.4 Exists查询
1
query = {"name": {"$exists" : 1}}
1.5 正则表达式查询
1
query = {"name": {"$regex" : "[Ff]riendship|[Pp]ride"}}
1.6 in查询
1
query = {"manufacturer":"Ford Motor Company","assembly":{"$in":["Germany","United Kingdom","Japan"]}}
1.7 all查询
1
query = {"manufacturer":"Ford Motor Company","assembly":{"$all":["Germany","United Kingdom","Japan"]}}
1.8点表示法
1
query = {"dimensions.width":{"$gt":2.5}}
2.更新
2.1 save()方法
1
2
3
4
city = db.cities.find_one({"name" : "Munchen"},
"country" : "Germany")
city["isoCountryCode"] = "DEU"
db.cities.save(city)
2.2 update()方法 set & unset
1
2
3
4
5
6
7
8
9
10
11
set:
city = db.cities.update({"name" : "Munchen"},
"country" : "Germany",
{"$set" : {"isoCountryCode" : "DEU"}}
)
unset:
city = db.cities.update({"name" : "Munchen"},
"country" : "Germany",
{"$set" : {"isoCountryCode" : ""}}
)
2.3 update()多项更新
1
2
3
4
city = db.cities.update({"name" : "Munchen"},
"country" : "Germany",
{"$set" : {"isoCountryCode" : ""}}
,multi = True)
3.删除

类似find语法

1
2
db.cities.remove(“name”: "Guangzhou", "class": "mid-size car")
db.cities.drop()删除collection所有内容

4.聚合框架
4.1聚合框架使用:
1
2
3
4
db.tweets.aggregate([
{“$group” : {"_id" : "$user.screen_name",
"count" : {"$sum" : 1}}},
{"$sort" : {"count" : -1}}])
4.2 match&project运算符:
1
2
3
4
5
6
7
8
db.tweets.aggregate([
{“$match” : {"user.friends_count" : {"$gt" : 0},
"user.followers_count": {"$gt" : 0}}},
{"$project": {"ratio" : {"$divide" : ["$user.followers_count",
"$user.friends_count"]},
"screen_name" : "$user.screen_name"}},
{"$sort" : {"ratio" : -1}},
{"$limit" : 1}])
4.3 unwind运算符:
1
2
3
4
5
db.tweets.aggregate([
{"$unwind" : "$entities.user_mentions"},
{“$group” : {"_id" : "$user.screen_name",
"count" : {"$sum" : 1}}},
{"sort" : {"count" : -1}}])
分组累加运算符:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$sum
$first
$last
$max
$min
$avg
$push (Arrays)
$addToSet (Arrays)
avg:
1
2
3
4
5
6
7
8
9
db.tweets.aggregate([
{"$unwind" : "$entities.hashtags"},
{“$group” : {"_id" : "$entities.hashtags.text",
"retweet_avg" : {"$avg" : "$retweet_count"}}},
{"sort" : {"retweet_avg" : -1}}])
addToSet:
1
2
3
4
5
6
7
8
9
10
11
db.tweets.aggregate([
{"$unwind" : "$entities.hashtags"},
{“$group” : {"_id" : "$entities.hashtags.text",
"unique_hashtags" : {"$addToSet" :
"$entities.hashtags.text"}}},
{"sort" : {"retweet_avg" : -1}}])