Python用csv模块处理二维数据——以10月杭州天气为例

一、CSV文件

逗号分隔值(Comma-Separated ValuesCSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。通常都是纯文本文件。建议使用记事本来打开编辑,或双击直接用Excel打开编辑。

()CSV文件用法

CSV是一种通用的、相对简单的文件格式,被用户、商业和科学广泛应用。最广泛的应用是在程序之间转移表格数据,而这些程序本身是在不兼容的格式上进行操作的(往往是私有的和/或无规范的格式)。因为大量程序都支持某种CSV变体,至少是作为一种可选择的输入/输出格式。

例如,有一批新生名单的Excel表文档,在将新生数据导入教学管理系统。最简单的方式是,将Excel数据导出为“CSV”,然后将导出的CSV文件导入到教学管理系统。

“CSV”并不是一种单一的、定义明确的格式(尽管RFC 4180有一个被通常使用的定义)。因此在实践中,术语“CSV”泛指具有以下特征的任何文件:

  1. 纯文本,使用某个字符集,比如ASCIIUnicodeEBCDICGBK
  2. 由记录组成(典型的是每行一条记录)
  3. 每条记录被分隔符分隔为字段(典型分隔符有逗号、分号或制表符;有时分隔符可以包括可选的空格)
  4. 每条记录都有同样的字段序列。

在这些常规的约束条件下,存在着许多CSV变体,故CSV文件并不完全互通。然而,这些变异非常小,并且有许多应用程序允许用户预览文件(这是可行的,因为它是纯文本),然后指定分隔符、转义规则等。如果一个特定CSV文件的变异过大,超出了特定接收程序的支持范围,那么可行的做法往往是人工检查并编辑文件,或通过简单的程序来修复问题。因此在实践中,CSV文件还是非常方便的。

本文讲的CSV文件是指逗号分隔值的纯文本(Excel样式),编码:Windows系统为GBKUNIX(Linux)一般为UTF-8。注:Win10记事本默认为UTF-8,Win7记事本默认为ANSI(GBK),MS Excel导出的csv文档是ANSI(GBK)

()CSV文件规则

  1. 开头是不留空,以行为单位。
  2. 可含或不含列名,含列名则居文件第一行。
  3. 一行数据不跨行,无空行。
  4. 半角逗号(“,”)作分隔符,列为空也要表达其存在。
  5. 列内容如存在半角引号("),替换成半角双引号("")转义,即用半角引号("")将该字段值包含起来。
  6. 文件读写时引号,逗号操作规则互逆。
  7. 内码格式不限,可为 ASCIIUnicodeANSIGBK或者其他。
  8. 不支持数字(数字以数值字符串表示)
  9. 不支持特殊字符

二、CSV模块

CSV模块是Python的标准模块,不需要安装就可使用。

() CSV模块的读方法(函数)

csv模块中的reader类和 DictReader类用于读取文件中的数据。

1. reader()

reader()语法格式如下:

csv.reader(csvfile, dialect='excel', **fmtparams)

其中:csvfile是支持迭代(Iterator)的对象,可以是文件(file)对象或者列表(list)对象;dialect是编码样式,默认为Excel的样式,也就是使用逗号“,”分隔符;fmtparams是格式化参数,用来覆盖之前 dialect 对象指定的编码样式。一般用于处理没有标题(列名)csv文件。

2. DictReader

DictReader语法格式如下:

csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel',

*args, **kwds)

其中:csvfile是csv文件对象;fieldnames 是一个序列,如果省略fieldnames,则文件对象第一行中的值将用作标题(列名)。不管标题是如何确定的,字典会保留它们的原始顺序。

如果一行的列多于标题列,则将剩余数据放入列表中并使用 restkey 指定的列名(默认为 None )存储。如果非空白行的列少于标题列,则缺少的值为 filled-in,值为 restval(默认为 None )

所有其他可选或关键词参数都传递给底层reader 对象。

DictReader将二维表的每行信息映射到字典(dict),其键为对应的标题。

(二) CSV模块的写方法(函数)

csv 模块中的writer类和DictWriter类用于将数据写入CSV文件中。

1. writer()

writer()的语法格式如下:

csv.writer(csvfile, dialect='excel', **fmtparams)

其中:csvfile是支持迭代(Iterator)的对象,可以是文件(file)对象或者列表(list)对象;dialect是编码样式,默认为Excel的样式,也就是使用逗号“,”分隔符;fmtparams是格式化参数,用来覆盖之前 dialect 对象指定的编码样式。

2. DictWriter()

csv.DictWriter(csvfile, fieldnames=None, restval =None, extrasaction ='raise', dialect='excel',

*args, **kwds)

其中:csvfilecsv文件对象;fieldnames 是一个序列,如果省略fieldnames,则文件对象第一行中的值将用作标题(列名)。不管标题是如何确定的,字典会保留它们的原始顺序。restval(可选)当如果字典缺少标题中的列, 则指定要写入的值。extrasaction(可选)如果在标题中找不到列, 则可选的extrasaction参数指示要执行的操作。如果将其设置为引发ValueError, 则会抛出异常。dialect (可选)是编码样式,默认为Excel的样式,也就是使用逗号“,”分隔符

csv.DictWriter提供了两种写入CSV的方法,writeheader()writerows()

writeheader()方法仅将标题写入csv文件的第一行。

语法如下:

writeheader()

writerows()方法只写所有行, 但在每一行中, 只写值(不写键)

语法如下:

writerows(mydict)

三、用csv模块处理二维数据应用实例

1是杭州市202210月份天气情况表,请用Python编程,将数据保存为csv文档,并读取数据编程绘制温度曲线。提示:可用turtle绘图。

表1 杭州市202210月份天气情况表

注:数据来自杭州历史气温_天气网

表中含有五列数据:日期、最高气温、最低气温、天气和风向,日期为2022年10月1日~2022年10月31日。这是带标题的二维数据,可以用Python的列表元素列表表示,也可以用Python的字典元素列表表示。相对于二维表格(如表1)转换为列表元素列表比较简单,转换为字典元素列表则相对要复杂些,用csv模块可以很方便地解决列表元素列表与字典元素列表间的转换。

(一) 用列表元素列表表示

用列表作为列表元素表示二维表时,数据的标题列表作为列表的第一个元素,每行数据都以值的列表表示,例如表1可以用下面的列表元素列表表示:

lst = [['日期','最高气温','最低气温','天气','风向'],
       ['2022-10-01 星期六','34℃','25℃','雾','东风 1级'],
       ['2022-10-02 星期日','37℃','26℃','晴','东南风 1级'],
       ['2022-10-03 星期一','38℃','24℃','晴','南风 1级'],
       ['2022-10-04 星期二','26℃','18℃','阴','北风 3级'],
       ['2022-10-05 星期三','20℃','15℃','多云','东北风 2级'],
       ['2022-10-06 星期四','16℃','14℃','小雨','北风 3级'],
       ['2022-10-07 星期五','15℃','14℃','小雨','北风 2级'],
       ['2022-10-08 星期六','17℃','15℃','小雨','北风 2级'],
       ['2022-10-09 星期日','19℃','10℃','多云','西北风 2级'],
       ['2022-10-10 星期一','19℃','9℃','晴','西北风 2级'],
       ['2022-10-11 星期二','19℃','12℃','多云','北风 2级'],
       ['2022-10-12 星期三','22℃','11℃','多云','东北风 1级'],
       ['2022-10-13 星期四','22℃','14℃','多云','东风 1级'],
       ['2022-10-14 星期五','24℃','15℃','多云','北风 2级'],
       ['2022-10-15 星期六','24℃','16℃','晴','东北风 2级'],
       ['2022-10-16 星期日','24℃','15℃','雾','北风 2级'],
       ['2022-10-17 星期一','21℃','10℃','雾','北风 2级'],
       ['2022-10-18 星期二','19℃','10℃','多云','北风 2级'],
       ['2022-10-19 星期三','20℃','11℃','晴','东风 2级'],
       ['2022-10-20 星期四','22℃','12℃','多云','东风 2级'],
       ['2022-10-21 星期五','26℃','16℃','多云','东风 2级'],
       ['2022-10-22 星期六','26℃','17℃','雾','北风 2级'],
       ['2022-10-23 星期日','23℃','11℃','雾','东北风 3级'],
       ['2022-10-24 星期一','22℃','13℃','多云','东风 2级'],
       ['2022-10-25 星期二','21℃','15℃','多云','东风 3级'],
       ['2022-10-26 星期三','20℃','16℃','阴','北风 1级'],
       ['2022-10-27 星期四','19℃','17℃','小雨','东北风 1级'],
       ['2022-10-28 星期五','18℃','14℃','小雨','东北风 2级'],
       ['2022-10-29 星期六','21℃','14℃','多云','东北风 2级'],
       ['2022-10-30 星期日','21℃','14℃','雾','东北风 1级'],
       ['2022-10-31 星期一','22℃','13℃','多云','西北风 2级']]

(二) 用字典元素列表表示

用字典作为列表元素表示二维表时,列标题作为键,每行数据对应列作为值的字典表示,例如表1可以用下面的字典元素列表表示:

dic = [{'日期': '2022-10-01 星期六', '最高气温': '34℃', '最低气温': '25℃', '天气': '雾', '风向': '东风 1级'}, 
       {'日期': '2022-10-02 星期日', '最高气温': '37℃', '最低气温': '26℃', '天气': '晴', '风向': '东南风 1级'}, 
       {'日期': '2022-10-03 星期一', '最高气温': '38℃', '最低气温': '24℃', '天气': '晴', '风向': '南风 1级'}, 
       {'日期': '2022-10-04 星期二', '最高气温': '26℃', '最低气温': '18℃', '天气': '阴', '风向': '北风 3级'}, 
       {'日期': '2022-10-05 星期三', '最高气温': '20℃', '最低气温': '15℃', '天气': '多云', '风向': '东北风 2级'}, 
       {'日期': '2022-10-06 星期四', '最高气温': '16℃', '最低气温': '14℃', '天气': '小雨', '风向': '北风 3级'}, 
       {'日期': '2022-10-07 星期五', '最高气温': '15℃', '最低气温': '14℃', '天气': '小雨', '风向': '北风 2级'}, 
       {'日期': '2022-10-08 星期六', '最高气温': '17℃', '最低气温': '15℃', '天气': '小雨', '风向': '北风 2级'}, 
       {'日期': '2022-10-09 星期日', '最高气温': '19℃', '最低气温': '10℃', '天气': '多云', '风向': '西北风 2级'}, 
       {'日期': '2022-10-10 星期一', '最高气温': '19℃', '最低气温': '9℃', '天气': '晴', '风向': '西北风 2级'}, 
       {'日期': '2022-10-11 星期二', '最高气温': '19℃', '最低气温': '12℃', '天气': '多云', '风向': '北风 2级'}, 
       {'日期': '2022-10-12 星期三', '最高气温': '22℃', '最低气温': '11℃', '天气': '多云', '风向': '东北风 1级'}, 
       {'日期': '2022-10-13 星期四', '最高气温': '22℃', '最低气温': '14℃', '天气': '多云', '风向': '东风 1级'}, 
       {'日期': '2022-10-14 星期五', '最高气温': '24℃', '最低气温': '15℃', '天气': '多云', '风向': '北风 2级'}, 
       {'日期': '2022-10-15 星期六', '最高气温': '24℃', '最低气温': '16℃', '天气': '晴', '风向': '东北风 2级'}, 
       {'日期': '2022-10-16 星期日', '最高气温': '24℃', '最低气温': '15℃', '天气': '雾', '风向': '北风 2级'}, 
       {'日期': '2022-10-17 星期一', '最高气温': '21℃', '最低气温': '10℃', '天气': '雾', '风向': '北风 2级'}, 
       {'日期': '2022-10-18 星期二', '最高气温': '19℃', '最低气温': '10℃', '天气': '多云', '风向': '北风 2级'}, 
       {'日期': '2022-10-19 星期三', '最高气温': '20℃', '最低气温': '11℃', '天气': '晴', '风向': '东风 2级'}, 
       {'日期': '2022-10-20 星期四', '最高气温': '22℃', '最低气温': '12℃', '天气': '多云', '风向': '东风 2级'}, 
       {'日期': '2022-10-21 星期五', '最高气温': '26℃', '最低气温': '16℃', '天气': '多云', '风向': '东风 2级'}, 
       {'日期': '2022-10-22 星期六', '最高气温': '26℃', '最低气温': '17℃', '天气': '雾', '风向': '北风 2级'}, 
       {'日期': '2022-10-23 星期日', '最高气温': '23℃', '最低气温': '11℃', '天气': '雾', '风向': '东北风 3级'}, 
       {'日期': '2022-10-24 星期一', '最高气温': '22℃', '最低气温': '13℃', '天气': '多云', '风向': '东风 2级'}, 
       {'日期': '2022-10-25 星期二', '最高气温': '21℃', '最低气温': '15℃', '天气': '多云', '风向': '东风 3级'}, 
       {'日期': '2022-10-26 星期三', '最高气温': '20℃', '最低气温': '16℃', '天气': '阴', '风向': '北风 1级'}, 
       {'日期': '2022-10-27 星期四', '最高气温': '19℃', '最低气温': '17℃', '天气': '小雨', '风向': '东北风 1级'}, 
       {'日期': '2022-10-28 星期五', '最高气温': '18℃', '最低气温': '14℃', '天气': '小雨', '风向': '东北风 2级'}, 
       {'日期': '2022-10-29 星期六', '最高气温': '21℃', '最低气温': '14℃', '天气': '多云', '风向': '东北风 2级'}, 
       {'日期': '2022-10-30 星期日', '最高气温': '21℃', '最低气温': '14℃', '天气': '雾', '风向': '东北风 1级'}, 
       {'日期': '2022-10-31 星期一', '最高气温': '22℃', '最低气温': '13℃', '天气': '多云', '风向': '西北风 2级'}]

(三) 二维数据csv文件

有标题的csv文档与无标题的csv文档的区别是:有标题的csv文档的第一行是标题,第二行开始才是数据;无标题的csv文档第一行开始就是数据。

1:将表1数据按有标题二维数据格式写到csv文件中,文档名为“d:\10月杭州天气.csv”

import csv

# 将数据保存为有标题(第一行为标题)的csv文档
lst = [['日期','最高气温','最低气温','天气','风向'],
       ['2022-10-01 星期六','34℃','25℃','雾','东风 1级'],
       ['2022-10-02 星期日','37℃','26℃','晴','东南风 1级'],
       ['2022-10-03 星期一','38℃','24℃','晴','南风 1级'],
       ['2022-10-04 星期二','26℃','18℃','阴','北风 3级'],
       ['2022-10-05 星期三','20℃','15℃','多云','东北风 2级'],
       ['2022-10-06 星期四','16℃','14℃','小雨','北风 3级'],
       ['2022-10-07 星期五','15℃','14℃','小雨','北风 2级'],
       ['2022-10-08 星期六','17℃','15℃','小雨','北风 2级'],
       ['2022-10-09 星期日','19℃','10℃','多云','西北风 2级'],
       ['2022-10-10 星期一','19℃','9℃','晴','西北风 2级'],
       ['2022-10-11 星期二','19℃','12℃','多云','北风 2级'],
       ['2022-10-12 星期三','22℃','11℃','多云','东北风 1级'],
       ['2022-10-13 星期四','22℃','14℃','多云','东风 1级'],
       ['2022-10-14 星期五','24℃','15℃','多云','北风 2级'],
       ['2022-10-15 星期六','24℃','16℃','晴','东北风 2级'],
       ['2022-10-16 星期日','24℃','15℃','雾','北风 2级'],
       ['2022-10-17 星期一','21℃','10℃','雾','北风 2级'],
       ['2022-10-18 星期二','19℃','10℃','多云','北风 2级'],
       ['2022-10-19 星期三','20℃','11℃','晴','东风 2级'],
       ['2022-10-20 星期四','22℃','12℃','多云','东风 2级'],
       ['2022-10-21 星期五','26℃','16℃','多云','东风 2级'],
       ['2022-10-22 星期六','26℃','17℃','雾','北风 2级'],
       ['2022-10-23 星期日','23℃','11℃','雾','东北风 3级'],
       ['2022-10-24 星期一','22℃','13℃','多云','东风 2级'],
       ['2022-10-25 星期二','21℃','15℃','多云','东风 3级'],
       ['2022-10-26 星期三','20℃','16℃','阴','北风 1级'],
       ['2022-10-27 星期四','19℃','17℃','小雨','东北风 1级'],
       ['2022-10-28 星期五','18℃','14℃','小雨','东北风 2级'],
       ['2022-10-29 星期六','21℃','14℃','多云','东北风 2级'],
       ['2022-10-30 星期日','21℃','14℃','雾','东北风 1级'],
       ['2022-10-31 星期一','22℃','13℃','多云','西北风 2级']]
with open(r'd:/10月杭州天气.csv','w',newline='') as f:
    csv.writer(f).writerows(lst)

程序执行结果如下:

1 例1执行结果

(四) 读有标题csv文档为字典元素列表

读取有标题的csv文档时,如以列表方式读,则处理时要丢弃第一行标题,获取数据按位置(索引值)获取,即按行、列获取某天的某个天气信息。如以字典方式读,则处理时第一行成为标题,获取数据按列标题获取,即可按条件、用列标题获取某天的某个天气信息。

如:

date = '2022-10-05'
print([i['天气'] for i in dic if i['日期'][:10] == date][0])

结果为:多云

2:读取例1保存10月杭州市天气情况“d:\10月杭州天气.csv”,绘制全月的最高温度和最低温度变化曲线,并在最高温度曲线上标注“天气”信息。

import csv
import turtle as tl

_maxt=[]										# 保存'最高温度'数据(数值)
_mint=[]										# 保存'最低温度'数据(数值)
with open(r'd:/10月杭州天气.csv','r') as f:		# 读数据,将标题转化为每列数据的“键”
    reader = csv.DictReader(f)					# 加fieldnames=head参数,则head为标题,
    dic_lst = list(reader)						#        第一行为数据,否则第一行为标题
    print(dic_lst)
    for i in dic_lst:							# 第i行数据
        _maxt.append(int(i['最高气温'][:-1]))	# '最高气温'列是某日最高温度,去掉℃转数值
        _mint.append(int(i['最低气温'][:-1]))	# '最低气温'列是某日最低温度,去掉℃转数值
tl.pu()
for i in range(31):								# 绘制日期文字(1日~31日)
    tl.goto(-300+i*20,-230)
    tl.write(str(i+1)+'\n日',align='center')
for i in range(5,40,5):							# 间隔5℃绘制温度文字(5~35℃)
    tl.goto(-305,-208+i*10)
    tl.write(str(i))
tl.goto(-305,-208+40*10)
tl.write('℃')									# 绘制温度坐标单位:℃
tl.goto(-310,-200)
tl.pd()
tl.fd(620)										# 绘制水平线(水平坐标线)
tl.lt(90)
for i in range(31,0,-1):						# 绘制31个日期刻度
    tl.pu()
    tl.goto(-300+(i-1)*20,-200)
    tl.pd()
    tl.fd(5)
tl.pu()
tl.goto(-310,-200)
tl.pd()
tl.fd(410)										# 绘制垂直线(垂直坐标线)
tl.rt(90)
for i in range(40,0,-1):						# 绘制40个温度刻度
    tl.pu()
    tl.goto(-310,-200+i*10)
    tl.pd()
    tl.fd(5)
tl.pu()
tl.goto(-300,-200+_maxt[0]*10)					# 移动到1日最高温度位置
tl.pd()
tl.color('red')									# 最高温度曲线用红色绘制
for i,t in enumerate(_maxt):					# 根据日期求水平、最高温度求垂直坐标
    tl.goto(-300+i*20,-200+t*10)
    tl.dot(6)									# 加小圆点
    tl.write(dic_lst[i]['天气'],align='center')	# 绘制天气信息(文字)
tl.pu()
tl.goto(-300,-200+_mint[0]*10)					# 移动到1日最低温度位置
tl.color('blue')								# 最低温度曲线用蓝色绘制
tl.pd()
for i,t in enumerate(_mint):					# 根据日期求水平、最低温度求垂直坐标
    tl.goto(-300+i*20,-200+t*10)
    tl.dot(6)									# 加小圆点
tl.ht()											# 隐藏LOGO形状

程序执行结果如图2所示。

 

2 例2执行结果(2022年10月最高温度和最低温度变化曲线)

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值