Python 读写 CSV 数据

news/2024/10/21 3:41:31/

问题

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

解决方案

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

Symbol,Price,Date,Time,Change,Volume
"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
"BA",98.31,"6/11/2007","9:36am",+0.12,104800
"C",53.08,"6/11/2007","9:36am",-0.25,360900
"CAT",78.29,"6/11/2007","9:36am",-0.23,225400

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

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

在上面的代码中,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)

它允许你使用列名如 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(',')

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

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

例如,如果你想 读取以 tab 分割的数据,可以这样做:

with open('stock.tsv') as f:
f_tsv = csv.reader(f, delimiter='\t')
for row in f_tsv:pass

如果你正在读取 CSV 数据并将它们转换为命名元组,需要注意对列名进行合法性 认证。
例如,可以像下面这样在非法标识符上使用 一个正则表达式替换:

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)

还有重要的一点需要强调的是,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:row = tuple(convert(value) for convert, value in zip(col_types, row))

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

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


http://www.ppmy.cn/news/51740.html

相关文章

为什么企业要做大规模敏捷?

背景 软件工程里一个重要的指标就是“可用的软件”,敏捷宣言里也同样告诉我们“工作的软件高于详尽的文档”,那“可用的软件”、“工作的软件”意味着什么呢?在我的理解里,可以经历用户 “千锤百炼”的软件就是一个“可用的软件”…

黑盒测试过程中【测试方法】详解4-因果图

在黑盒测试过程中,有9种常用的方法:1.等价类划分 2.边界值分析 3.判定表法 4.正交实验法 5.流程图分析 6.因果图法 7.输入域覆盖法 8.输出域覆盖法 9.猜错法 黑盒测试过程中【测试方法】讲解1-等价类,边界值,判定表_朝一…

《ChatGPT开发应用指南》,Datawhale开源了!

Datawhale发布 开源教程:HuggingLLM,Datawhale团队 随着ChatGPT的爆火,我们相信未来会有越来越多的大模型及类似OpenAI提供的服务出现,AI 正在逐渐平民化,将来每个人都可以利用大模型轻松地做出自己的AI产品。 Huggin…

利用ArcGIS软件赋予tif影像空间参考坐标系

问题: 在处理数据时有一幅没有任何空间参考坐标信息的tif影像,实质上为一个照片。现在需要将其与一个有空间地理参考坐标信息的shp文件叠加在一起。如何解决这个问题呢? 已知信息: shp文件的空间地理参考 shp文件的边界与tif影像的…

链表篇总结

移除链表元素: 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 思路: 这里以链表 1 4 2 4 来举例,移除元素4。 那么因为单链表的特殊性,只…

vue安装初始化项目

安装vue脚手架启动项目 1、nvm安装vue 当前nvm使用的node版本是v10.24.1 npm install -g vue/cli安装完成之后报错: You are using Node v10.24.1, but this version of vue/cli requires Node ^12.0.0 || > 14.0.0. Please upgrade your Node version. 显而易…

2379. 得到 K 个黑块的最少涂色次数

2379. 得到 K 个黑块的最少涂色次数 给你一个长度为 n 下标从 0 开始的字符串 blocks ,blocks[i] 要么是 ‘W’ 要么是 ‘B’ ,表示第 i 块的颜色。字符 ‘W’ 和 ‘B’ 分别表示白色和黑色。 给你一个整数 k ,表示想要 连续 黑色块的数目。…

JavaWeb+在线图书商城+Ajax(异步的 JavaScript 和 XML)(超详细)

🙈作者简介:练习时长两年半的Java up主 🙉个人主页:老茶icon 🙊 ps:点赞👍是免费的,却可以让写博客的作者开兴好久好久😎 📚系列专栏:Java全栈,计…