七天学会Python编程 -- 第八章 数据分析

8.1 数据分析是什么?

数据分析是根据一些分析方法对数据进行计算、汇总等操作,输出比较有价值的结果。

比如我们有了一个班级所有学生的全部科目的考试成绩,就可以做各种数据分析了,我们可以计算一下每科所有学生的平均分,也可以计算每个学生所有科目的总分和平均分,可以排列总分名次,也可以排列平均分名次。

进一步可以对某科目的分数段做统计,统计出90分到100分有多少个学生,低于60分的有多少个学生。

这里只是举了个实际中可能用到的例子,可以根据需要做多种个性化分析。

分析数据来源可以是一个表格数据文件,也可以是数据库,或者其他来源。

主要过程就是:加载源数据 -> 根据需要做数据统计运算 -> 输出统计结果。

8.2 一个有趣的分析案例

我们通过一个有趣的案例来深入讲解一下,比如我们拿到这样的记录一个城市天气状况的源数据文件,是 CSV 格式的,可以用 Excel 打开浏览。

Date,Type Of Weather,Average Temperature

2015-1-1,Sunny,8

2015-1-2,Sunny,9

2015-1-3,Cloudy,8

2015-1-4,Rainy,7

2015-12-31, Sunny, 10

这个文件记录了日期、天气类型、平均气温这3个数据,每天一条记录,包含了 2015 年一年的数据,我们现在通过程序做几个分析,一个分析是统计一下 Sunny 天气总共有多少天,Cloudy 天气总共有多少天,和 Rainy 天气总共有多少天。

首先我们要读取文件内容:

1
file = open("weather2015.csv", "r")

然后读取整个文件内容:

1
fileContent = file.read()

然后要解析数据,因为现在读到的是整个文件所有数据,都放在一个大字符串 fileContent 里了。

现在学一个字符串的方法 split,是按某个字符拆分一个字符串成一个列表,现在 fileContent 里的大字符串是用回车符号 \n 分割成各行,每行又用逗号 , 分割成多列,我们先用 split 方法来拆分每行数据。

1
lines = fileContent.split("\n")

split 方法是属于字符串对象 fileContent 的,它需要一个分割字符做参数,拆分后的列表返回给 lines 变量。

下面再拆分每行,需要用循环遍历 lines 中每行,

1
2
3
4
5
rows = []

for line in lines:
rowData = line.split(",")
rows.append(rowData)

上面代码先定义了一个列表 rows,用于保存拆分后的每行列表对象,然后循环遍历 lines 列表,对每行字符串再使用 split 方法,这次是用逗号 , 做参数,把拆分完的列表追加到 rows 列表中,最后 rows 中的数据是这样的:

[ [“2015-1-1”, “Sunny”, “8” ], [“2015-1-2”, “Sunny”, “9” ], … ]

现在才开始进入数据分析阶段,前面我们做的都是数据加载方面的处理。

数据统计分析需要用到字典类型对象了,这次我们要统计 Sunny 天气类型在一年内有多少天,我们可以定义一个字典类型对象:

1
results = {}

空的大花号就表示一个空的字典对象,我们把这个字典对象赋予 results 这个变量。

1
results["Sunny"] = 0

这样就在字典对象里增加一个数据,Key 是 “Sunny”,对应的数据是 0,我们可以用这样的方式改变 Key 对应的数据:

1
results["Sunny"] = results["Sunny"] + 1

这行代码是把 “Sunny” 这个 Key 对应的数值加1,运行后 results[“Sunny”] 的数据变成 1,以前是 0,加 1 就变成 1.

我们就是用这种思路来统计数据中 “Sunny” 的天气天数,也就是遍历那些从文件中加载的数据,每当碰到 “Sunny” 类型的天气,就把 results[“Sunny”] 加 1,循环遍历完后 results[“Sunny”] 就保存了 “Sunny” 天气的天数。下面看一下代码:

1
2
3
4
5
6
7
results["Sunny"] = 0

for row in rows:
if row[1] == "Sunny":
results["Sunny"] = results["Sunny"] + 1

print(results["Sunny"])

上面代码是遍历我们前面已经加载好的数据,每行数据都是一个列表,其中第二个数据是天气类型,就判断这个天气类型是否是 “Sunny”,如果是就把 results[“Sunny”] 加 1。遍历完毕后就计算好了 “Sunny” 天气的天数,现在我们再把 “Cloudy” 和 “Rainy” 天气的天数也计算一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
results["Sunny"] = 0
results["Cloudy"] = 0
results["Rainy"] = 0

for row in rows:
if row[1] == "Sunny":
results["Sunny"] = results["Sunny"] + 1

if row[1] == "Cloudy":
results["Cloudy"] = results["Cloudy"] + 1

if row[1] == "Rainy":
results["Rainy"] = results["Rainy"] + 1


print(results)

现在那几种天气类型的天数都计算出来。

现在我们改进一下程序,如果我们要计算的天气类型有很多种,我们预先也不知道有哪几种,但我们需要统计出来有几种,而且每种有多少天。

这就需要用到字段对象的一个长处了,我们可以先不用定义各个 Key 及对应的初始值,我们可以直接在循环里用那个天气类型作为 Key 值,并做加 1 处理,下面看一下代码:

1
2
3
4
5
6
7
8
9
results = {}

for row in rows:
if row[1] in results:
results[ row[1] ] = results[ row[1] ] + 1
else:
results[ row[1] ] = 0

print( results )

现在代码是不是比较清爽,我们分析一下,一开始先定义一个字段对象,赋给变量 results,然后遍历加载的数据,判断每行中的天气类型那个数据有没有在 results 这个字段对象的 Key 里,如果有,就直接加 1,如果没有就初始化为 0,为后面加 1 做准备。最后打印出统计结果。

现在我们把上面几部分代码放到一起:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
file = open("weather2015.csv", "r")

fileContent = file.read()
lines = fileContent.split("\n")

rows = []

for line in lines:
rowData = line.split(",")
rows.append(rowData)

results = {}

for row in rows:
if row[1] in results:
results[ row[1] ] = results[ row[1] ] + 1
else:
results[ row[1] ] = 0

print( results )

8.3 实践练习时间

过去章节我们学习了数据分析相关内容,下面通过实践练习来理解。

练习1:

仿照前面章节的数据分析例子,写一个程序,统计一下那一年内的数据中各个平均温度都有多少天?统计出来的结果可能是这样的:

results[8] = 25

results[9] = 93

results[10] = 101

数据文件自己建一个,类似这样格式:

Date,Type Of Weather,Average Temperature

2015-1-1,Sunny,8

2015-1-2,Sunny,9

2015-1-3,Cloudy,8

2015-1-4,Rainy,7

2015-12-31, Sunny, 10

不需要一年365天都有,有一部分就可以。