Python如何读取、写入CSV数据


Posted in Python onJuly 28, 2020

问题

你想读写一个CSV格式的文件。

解决方案

对于大多数的CSV格式的数据读写问题,都可以使用 csv 库。、例如,假设你在一个名叫stocks.csv文件中有一些股票市场数据,就像这样:

下面向你展示如何将这些数据读取为一个元组的序列:

import csv
with open('stocks.csv') as f:
 f_csv = csv.reader(f)
 headers = next(f_csv)
 for row in f_csv:
  # Process row
  ...

在上面的代码中,row 会是一个元组。因此,为了访问某个字段,你需要使用下标,如row[0]访问Symbol,row[4]访问Change。

由于这种下标访问通常会引起混淆,你可以考虑使用命名元组。例如:

from collections import namedtuple
with open('stock.csv') as f:
 f_csv = csv.reader(f)
 headings = next(f_csv)
 Row = namedtuple('Row', headings)
 for r in f_csv:
  row = Row(*r)
  # Process row
  ...

它允许你使用列名如 row.Symbol 和 row.Change 代替下标访问。需要注意的是这个只有在列名是合法的Python标识符的时候才生效。如果不是的话,你可能需要修改下原始的列名(如将非标识符字符替换成下划线之类的)。

另外一个选择就是将数据读取到一个字典序列中去。可以这样做:

import csv
with open('stocks.csv') as f:
 f_csv = csv.DictReader(f)
 for row in f_csv:
  # process row
  ...

在这个版本中,你可以使用列名去访问每一行的数据了。比如,row['Symbol'] 或者 row['Change'] 。

为了写入CSV数据,你仍然可以使用csv模块,不过这时候先创建一个 writer 对象。例如;

headers = ['Symbol','Price','Date','Time','Change','Volume']
rows = [('AA', 39.48, '6/11/2007', '9:36am', -0.18, 181800),
   ('AIG', 71.38, '6/11/2007', '9:36am', -0.15, 195500),
   ('AXP', 62.58, '6/11/2007', '9:36am', -0.46, 935000),
  ]

with open('stocks.csv','w') as f:
 f_csv = csv.writer(f)
 f_csv.writerow(headers)
 f_csv.writerows(rows)

如果你有一个字典序列的数据,可以像这样做:

headers = ['Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']
rows = [{'Symbol':'AA', 'Price':39.48, 'Date':'6/11/2007',
  'Time':'9:36am', 'Change':-0.18, 'Volume':181800},
  {'Symbol':'AIG', 'Price': 71.38, 'Date':'6/11/2007',
  'Time':'9:36am', 'Change':-0.15, 'Volume': 195500},
  {'Symbol':'AXP', 'Price': 62.58, 'Date':'6/11/2007',
  'Time':'9:36am', 'Change':-0.46, 'Volume': 935000},
  ]

with open('stocks.csv','w') as f:
 f_csv = csv.DictWriter(f, headers)
 f_csv.writeheader()
 f_csv.writerows(rows)

讨论

你应该总是优先选择csv模块分割或解析CSV数据。例如,你可能会像编写类似下面这样的代码:

with open('stocks.csv') as f:
for line in f:
 row = line.split(',')
 # process row
 ...

使用这种方式的一个缺点就是你仍然需要去处理一些棘手的细节问题。比如,如果某些字段值被引号包围,你不得不去除这些引号。另外,如果一个被引号包围的字段碰巧含有一个逗号,那么程序就会因为产生一个错误大小的行而出错。

默认情况下,csv 库可识别Microsoft Excel所使用的CSV编码规则。这或许也是最常见的形式,并且也会给你带来最好的兼容性。然而,如果你查看csv的文档,就会发现有很多种方法将它应用到其他编码格式上(如修改分割字符等)。例如,如果你想读取以tab分割的数据,可以这样做:

# Example of reading tab-separated values
with open('stock.tsv') as f:
 f_tsv = csv.reader(f, delimiter='\t')
 for row in f_tsv:
  # Process row
  ...

如果你正在读取CSV数据并将它们转换为命名元组,需要注意对列名进行合法性认证。例如,一个CSV格式文件有一个包含非法标识符的列头行,类似下面这样:

这样最终会导致在创建一个命名元组时产生一个 ValueError 异常而失败。为了解决这问题,你可能不得不先去修正列标题。例如,可以像下面这样在非法标识符上使用一个正则表达式替换:

import re
with open('stock.csv') as f:
 f_csv = csv.reader(f)
 headers = [ re.sub('[^a-zA-Z_]', '_', h) for h in next(f_csv) ]
 Row = namedtuple('Row', headers)
 for r in f_csv:
  row = Row(*r)
  # Process row
  ...

还有重要的一点需要强调的是,csv产生的数据都是字符串类型的,它不会做任何其他类型的转换。如果你需要做这样的类型转换,你必须自己手动去实现。下面是一个在CSV数据上执行其他类型转换的例子:

col_types = [str, float, str, str, float, int]
with open('stocks.csv') as f:
 f_csv = csv.reader(f)
 headers = next(f_csv)
 for row in f_csv:
  # Apply conversions to the row items
  row = tuple(convert(value) for convert, value in zip(col_types, row))
  ...

另外,下面是一个转换字典中特定字段的例子:

print('Reading as dicts with type conversion')
field_types = [ ('Price', float),
    ('Change', float),
    ('Volume', int) ]

with open('stocks.csv') as f:
 for row in csv.DictReader(f):
  row.update((key, conversion(row[key]))
    for key, conversion in field_types)
  print(row)

通常来讲,你可能并不想过多去考虑这些转换问题。在实际情况中,CSV文件都或多或少有些缺失的数据,被破坏的数据以及其它一些让转换失败的问题。因此,除非你的数据确实有保障是准确无误的,否则你必须考虑这些问题(你可能需要增加合适的错误处理机制)。

最后,如果你读取CSV数据的目的是做数据分析和统计的话,你可能需要看一看 Pandas 包。Pandas 包含了一个非常方便的函数叫 pandas.read_csv() ,它可以加载CSV数据到一个 DataFrame 对象中去。然后利用这个对象你就可以生成各种形式的统计、过滤数据以及执行其他高级操作了。

以上就是Python如何读写CSV数据的详细内容,更多关于Python读写CSV数据的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
详解Python实现按任意键继续/退出的功能
Aug 19 Python
Python 编码处理-str与Unicode的区别
Sep 06 Python
NumPy 数组使用大全
Apr 25 Python
用python建立两个Y轴的XY曲线图方法
Jul 08 Python
Python产生一个数值范围内的不重复的随机数的实现方法
Aug 21 Python
python dumps和loads区别详解
Feb 04 Python
Python使用type动态创建类操作示例
Feb 29 Python
Python实现初始化不同的变量类型为空值
Jun 02 Python
使用Keras 实现查看model weights .h5 文件的内容
Jun 09 Python
python获取命令行参数实例方法讲解
Nov 02 Python
浅谈matplotlib默认字体设置探索
Feb 03 Python
简述python四种分词工具,盘点哪个更好用?
Apr 13 Python
PyQt中使用QtSql连接MySql数据库的方法
Jul 28 #Python
pycharm全局搜索的具体步骤
Jul 28 #Python
Django model重写save方法及update踩坑详解
Jul 27 #Python
matplotlib 画双轴子图无法显示x轴的解决方法
Jul 27 #Python
虚拟机下载python是否需要联网
Jul 27 #Python
详解在Python中使用Torchmoji将文本转换为表情符号
Jul 27 #Python
基于python实现操作git过程代码解析
Jul 27 #Python
You might like
PHP新手上路(五)
2006/10/09 PHP
php删除与复制文件夹及其文件夹下所有文件的实现代码
2013/01/23 PHP
使用迭代器 遍历文件信息的详解
2013/06/08 PHP
php自定义类fsocket模拟post或get请求的方法
2015/07/31 PHP
php实现多城市切换特效
2015/08/09 PHP
获取数组中最大最小值方法js代码(自写)
2013/08/12 Javascript
javascript页面渲染速度测试脚本分享
2014/04/15 Javascript
jQuery处理图片加载失败的常用方法
2015/06/08 Javascript
jQuery实现切换页面过渡动画效果
2015/10/29 Javascript
JavaScript+html5 canvas绘制缤纷多彩的三角形效果完整实例
2016/01/26 Javascript
jQuery基于$.ajax设置移动端click超时处理方法
2016/05/14 Javascript
浅谈如何实现easyui的datebox格式化
2016/06/12 Javascript
AngularJS Phonecat实例讲解
2016/11/21 Javascript
12 款 JS 代码测试必备工具(翻译)
2016/12/13 Javascript
Vue2.x中利用@font-size引入字体图标报错的解决方法
2018/09/28 Javascript
JS实现根据数组对象的某一属性排序操作示例
2019/01/14 Javascript
vue防止花括号{{}}闪烁v-text和v-html、v-cloak用法示例
2019/03/13 Javascript
js实现贪吃蛇游戏 canvas绘制地图
2020/09/09 Javascript
[46:00]Ti4 冒泡赛第二轮LGD vs C9 2
2014/07/14 DOTA
Python如何通过subprocess调用adb命令详解
2017/08/27 Python
Python3 实现串口两进程同时读写
2019/06/12 Python
PyQt5的安装配置过程,将ui文件转为py文件后显示窗口的实例
2019/06/19 Python
python 搜索大文件的实例代码
2019/07/08 Python
python requests使用socks5的例子
2019/07/25 Python
Django 开发环境与生产环境的区分详解
2019/07/26 Python
Flask框架实现的前端RSA加密与后端Python解密功能详解
2019/08/13 Python
PyTorch: 梯度下降及反向传播的实例详解
2019/08/20 Python
tensorflow中tf.reduce_mean函数的使用
2020/04/19 Python
python 用opencv实现图像修复和图像金字塔
2020/11/27 Python
Stefania Mode美国:奢华设计师和时尚服装
2018/01/07 全球购物
如何理解委托
2012/01/06 面试题
Java中的基本数据类型所占存储空间大小固定的吗
2012/02/15 面试题
房产授权委托书范本
2014/09/22 职场文书
关于长城的导游词
2015/01/30 职场文书
建筑工程材料员岗位职责
2015/04/11 职场文书
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
2022/03/16 Redis