数据分析其实是一种统计方法,它的特点是多维性和描述性,可以通过数据和图表揭示不同数据之间的关联,并进行信息统计,用更简洁的方式描绘复杂数据所包含的主要信息,这样就是数据分析的真谛了。

举个实际例子来说:上司丢给我们一堆数据,其中包含了历年以来的销售数据,我们需要从中找出增长规律,客户的属性,人员成本等等。

这个过程可能是人工的、手动的,相信有不少读者在这方面比我更有经验,上司或老板要的是报表,我们要的是如何快速准确的按要求出一张报表。

如果数据来源和内容更加复杂,可能分布在不同的文件里,或者是部分数据还存在于不同的数据库中,数据内容也不是特别规范的话,那我们就需要用到编程语言对数据进行清洗再进行分析了。

这个教程系列主要讲述利用 Python和其相关的组件进行数据分析的工作,主旨是为了让我们通过本系列的学习掌握Pyhton数据分析的基本思路和方法,学会一些常见分析工具的使用。让原来需要很长时间才能完成的报表分析工作在更短的时间内完成。

本章知识点:

  • Python读写CSV文件
  • Python读写Excel文件

关于数据分析的行为,我们每个人对它的理解和认识都不一样,有人觉得数据分析就是把已有的数据文件(比如Excel) 打开进行查阅,有人觉得数据分析是从数据库里按照需求用SQL语句查询数据,甚至是通过互联网爬虫去抓取数据并进行分析。

不过总结起来主要还是对文件进行的读取,所谓的数据库也是存储在文件系统里,只是中间多封装了一个结构化的数据层而已。


Python读取CSV文件


CSV文件也叫逗号分隔值文件(Comma-Separated Values),每一组数据之间通过逗号分割(少部分时候也可以用其他符号分割)CSV文件的特点是以纯文本的形式存储表格数据,因为CSV是纯文本的文件,所以我们可以认为它是一个字符序列,不需要像读取二进制那样的方式来读取文件内容。

以下是一个简单的CSV文件的格式。


我用文本编辑器遍写了一个CSV文件,命名为三国武将表.csv。

  • 第一行是表头,用于描述每一列数据的用处,每一列通过逗号分隔。
  • 第二行开始连续定义了三个武将的属性信息,同样每一列数据都通过逗号分隔。


现在我们可以用Excel或者别的电子表格软件打开这个CSV文件,看看是它是如何展现数据的。


假设我们在做一个关于三国的游戏,这个武将表的信息将直接被读取到内存里展现到游戏画面里,那么我们就需要随时对数据进行修改和保存,现在就需要借助到Python读写CSV文件了。

因为Python标准库里自带了对CSV文件对读写支持,所以我们可以直接使用 import csv 来导入CSV文件处理模块。


详细代码和运行结果如下:


通过以上代码,我们首先import csv这个Python自带的模块。

打开本地文件 "三国武将表.csv" 设置为变量f。

通过csv.reader()将 f 变量所代表文件对象转换为csv文件对象 f_csv。

这个时候 f_csv对象其实是一个可迭代对象,我们对其进行for循环即可打印出每一行的内容了,而每一行的内容就是一个list(列表),它由每一列的数据组成,很直观。

现在有一个新的需求,我们希望对随机减掉每个武将的血量,让数据看起来像是刚刚打完一场仗 (吕布此刻正在虎牢关单挑关羽张飞呢)

现在重新改造一下刚才的代码实现修改武将血量。


如上图所示我们实现了武将血量的随机减少。

在代码里我们主要加了一个叫random的Python标准库,它的主要用处是用来产生随机数。

在代码第9行,我们对row的元素下标为2的值随机减去了一些值,之所以不直接用row[2]而需要用int(row[2])转换数据为整型数字,原因是CSV文件默认读取进来都是字符串类型的,如果我们希望某列数据是数字的话就需要在使用时进行数据转换。

现在我们已经对几个武将的血量进行了改变,不过武将的数据还在内存中,我们来把信息保存到CSV文件里。


Python保存CSV文件

以上代码我们做了很少的改动,首先定了一个rows列表变量,用于存储武将属性变动后的数据。

在15行的 rows.append(row) 用于把每条改变的数据新增到 rows里。

在第19行,我们用 w文件模式打开了一个新的文件 "三国武将列表_2.csv"用于写一个新的CSV文件。

通过csv.write(f)把文件对象变成csv的模块对象,然后调用writerows()方法写入文件信息。

需要注意的是在这段程序里我用到了一个 try except的语法用于异常处理,因为第一行表头数据中的 row[2]取到的 “血量” 是文字信息,我们是不可能对其进行加减操作的。

当我们预先料到程序会报错时就可以用try except来处理异常,在except里写一个pass表示如果程序报错了什么都不用管,跳过即可。(关于Python的异常处理请参考 纸飞机编程的Python基础教程系列)

现在来看看写入的CSV文件,会发现每一个武将的血量都产生了变化。

可能有读者会好奇,我们的f_csv.writerows(rows) 究竟写的是什么东西?我们在代码里把rows信息打印出来看看。


在第18行,我们print了rows这个变量的信息,会发现它其实就是包含了多个子列表的列表对象。每一个子列表里包含了多个列的数据。


Python读取Excel文件


讲完了CSV文件的读写后再来讲讲Excel文件。

Excel是微软在1982年出品的一款电子表格软件,因为它界面直观,计算和图表功能很不错,再加上在当时市场上几乎没有能打的对手,历经这么多年后,Excel文件几乎成为了电子表格的行业标准。

我们需要将Excel文件和Excel软件区分开,Excel文件格式扩展名一般叫做xls或者xlsx,它可以由微软的Excel软件打开编辑,同样可以被其他的软件进行编辑,例如WPS、Numbers等等。

现在我们可以把刚才的CSV文件先另存为一个Excel格式的文件吧,因为CSV文件已经在我的电脑里被Numbers软件打开了,所以我直接把它另存为xlsx格式的文件即可。


现在就可以得到一个名为 “三国武将表.xlsx的文件"。

那么如何在 Python里读取一个Excel文件呢?

在Python的生态环境里,提供了大量支持操作Excel文件格式的第三方库,在本章教程里,我只用 xlrd 和xlwt 这两个库来讲解。

  • 通过pip install xlwt xlrd安装这两个第三方库
  • xlrd用于读取Excel文件
  • xlwt用于写入Excel文件

xlrd读取Excel文件


以上代码展示了如何通过xlrd库读取一个Excel文件。

  • 首先 import xlrd 引用 xlrd 库。
  • 通过 xlrd.open_workbook()打开一个Excel文件并得到一个xlrd.book.Book 的对象(以下简称book对象)。
  • xlrd的 Book 对象有一个 sheets() 的方法,用于得到一个表格文件的所有工作表对象,相信工作表大家在日常工作中都已见过,在这就不再累述了。
  • 因为我们在这个表格里只有一张工作表,所以我们取工作表对象的下标第0个元素即可得到第一张工作表的内容,将其赋值给变量table
  • 在第9行开始遍历工作表,通过 table.nrows这个属性获取表格的行数。通过range(1, 表格行数) 即可获得一个可遍历4行的可迭代对象,每次将行号赋值给 rownum 。
  • 通过 table.row(rownum)方法可以根据行号得到一行的所有数据(rownum是行号)。

我们注意到每一列的数据前面会有一个 text或者 number的文字,它其实是用于区分数据类型究竟是字符串还是数字。

我们讲过CSV文件内容都是字符类型的,如果是Excel文件,并且通过xlrd库读取的时候,它会自动将数字和字符区隔开,不用我们在处理时进行数据类型转换。

现在我们同样对每个武将的血量进行随机改变,用于学习如何通过Python处理Excel数据。


因为第一行数据是表头,所以对 rownum 进行判断,在第2行才开始对血量进行改变。

我们需要在程序里大量用到每一行数据的对象 table.row(rownum),但是在每一个地方写这个玩意显得琐碎,所以用了一个row_vals存储每一行数据。

row_vals是每一行数据,通过取元素下标位可以获得每一列的数据,再访问其 value 属性即可获取每一列的具体内容了 row_vals[2].value。

最后我们看到吕布、关羽、张飞的血量都已经被改变了,而且张飞都快挂了。。。。。。

现在我们来学习如何将数据写入Excel文件。


xlwt写入Excel文件


以上代码解读如下:

  • 因为我们写入Excel表需要有至少一个列表对象,并且里面包含1到多个子列表,每个子列表对应的就是每一行的数据。
  • 所以我们在代码11行定义了一个空的列表 datas,在代码17行把每一条修改之后对子列表数据通过列表的append()方法把子列表添加到datas里。
  • 在第20行定义了一个xlwt的Workbook对象,设置为变量book,并且在21行调用book对add_sheet()方法添加一张新的工作表,赋值给变量sheet。如果需要在Excel文件里添加多个工作表,那就需要多做几次add_sheet()操作分别赋值。
  • 最后我们来看看 sheet.write()方法,它接受三个参数,分别是(行号,列号,数据内容)。因为write()每次只能写入一列数据,所以我们需要明确的告诉它在第几行,第几列写入什么数据。
  • 基于write()的参数要求,我做了一个双重for循环,第一层for 循环取出 rownum和 val,rownum变量是行号,每一行的数据列表的变量是val,再在下一层循环里对val进行遍历,取出列表的元素下标和具体的值,这里的i和j分别就对应着列号和具体的值了,大家在脑子里过一遍,模拟一下这个双重for循环的过程,至于enumerate内置函数的作用就是对一个可迭代对象取值,分别得到其元素下标位和值。
  • 最后通过book.save()把表格数据保存为文件

为了方便理解数据格式,我们把datas的内容打印出来看看。


通过以上截图我们可以发现其实datas的内容就是列表里嵌套了多个子列表,对其进行双重for循环,盘它就是了。


现在来看看输出Excel文件结果:


通过对xlrd和xlwt两个库的结合使用,我们可以避免很多重复性的劳动,完成更多有趣的工作。


最后我们通过一个思维导图来总结一下本章的所有知识点。



本章教程到此结束,关于CSV文件和Excel文件其实还有更多的读写方法,我们将在以后的章节里一一讲解。

欢迎关注我 “纸飞机编程”,获取更多有趣的Python编程信息。