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中MYSQLdb出现乱码的解决方法
Oct 11 Python
python使用参数对嵌套字典进行取值的方法
Apr 26 Python
详解如何用TensorFlow训练和识别/分类自定义图片
Aug 05 Python
Python中调用其他程序的方式详解
Aug 06 Python
Python代理IP爬虫的新手使用教程
Sep 05 Python
wxPython:python首选的GUI库实例分享
Oct 05 Python
Python socket模块ftp传输文件过程解析
Nov 05 Python
tensorboard 可以显示graph,却不能显示scalar的解决方式
Feb 15 Python
Python 自由定制表格的实现示例
Mar 20 Python
Python3-异步进程回调函数(callback())介绍
May 02 Python
golang/python实现归并排序实例代码
Aug 30 Python
python实现MD5进行文件去重的示例代码
Jul 09 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开发框架myqee新手快速入门教程
2014/07/14 PHP
PHP常见加密函数用法示例【crypt与md5】
2019/01/27 PHP
TP5框架页面跳转样式操作示例
2020/04/05 PHP
CSS JavaScript 实现菜单功能 改进版
2008/12/09 Javascript
js自执行函数的几种不同写法的比较
2012/08/16 Javascript
JS字符串拼接在ie中都报错的解决方法
2014/03/27 Javascript
js在数组中删除重复的元素自保留一个(两种实现思路)
2014/08/22 Javascript
jQuery源码解读之hasClass()方法分析
2015/02/20 Javascript
javascript常见数据验证插件大全
2015/08/03 Javascript
jQuery滚动新闻实现代码
2016/06/26 Javascript
nodejs微信公众号支付开发
2016/09/19 NodeJs
JS实现给对象动态添加属性的方法
2017/01/05 Javascript
利用原生js实现html5小游戏之打砖块(附源码)
2018/01/03 Javascript
微信小程序自定义弹窗实现详解(可通用)
2019/07/04 Javascript
ES6中new Function()语法及应用实例分析
2020/02/19 Javascript
js瀑布流布局的实现
2020/06/28 Javascript
js节流防抖应用场景,以及在vue中节流防抖的具体实现操作
2020/09/21 Javascript
[51:10]VP vs VGJ.S 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python使用urllib2模块抓取HTML页面资源的实例分享
2016/05/03 Python
python安装mysql-python简明笔记(ubuntu环境)
2016/06/25 Python
Django中使用第三方登录的示例代码
2018/08/20 Python
Python高斯消除矩阵
2019/01/02 Python
对python3中, print横向输出的方法详解
2019/01/28 Python
Python enumerate函数功能与用法示例
2019/03/01 Python
Python中SQLite如何使用
2020/05/27 Python
keras分类模型中的输入数据与标签的维度实例
2020/07/03 Python
python里glob模块知识点总结
2021/01/05 Python
基于HTML5的WebGL经典3D虚拟机房漫游动画
2017/11/15 HTML / CSS
采用专利算法搜索最廉价的机票:CheapAir
2016/09/10 全球购物
广州足迹信息技术有限公司Java软件工程师试题
2014/02/15 面试题
中间件的定义
2016/08/09 面试题
三查三看党性分析材料
2014/02/18 职场文书
ktv筹备计划书
2014/05/03 职场文书
客运企业隐患排查工作方案
2014/06/06 职场文书
纪律教育学习月活动总结
2014/08/27 职场文书
2016年领导干部廉政承诺书
2016/03/24 职场文书