许多生物信息学数据都存储在文本文件中, 每行一条记录,列之间用逗号(csv文件)或 tab 键(表格文件)隔开。
解决方案
代码语言:javascript复制import csv
with open('iris.csv') as f:
f_csv = csv.reader(f)
headers = next(f_csv)
for row in f_csv:
print(row)
输出内容:
代码语言:javascript复制['5.1', '3.5', '1.4', '0.2', 'setosa']
['4.9', '3', '1.4', '0.2', 'setosa']
['4.7', '3.2', '1.3', '0.2', 'setosa']
['4.6', '3.1', '1.5', '0.2', 'setosa']
['5', '3.6', '1.4', '0.2', 'setosa']
['5.4', '3.9', '1.7', '0.4', 'setosa']
['4.6', '3.4', '1.4', '0.3', 'setosa']
['5', '3.4', '1.5', '0.2', 'setosa']
['4.4', '2.9', '1.4', '0.2', 'setosa']
['4.9', '3.1', '1.5', '0.1', 'setosa']
['5.4', '3.7', '1.5', '0.2', 'setosa']
['4.8', '3.4', '1.6', '0.2', 'setosa']
['4.8', '3', '1.4', '0.1', 'setosa']
['4.3', '3', '1.1', '0.1', 'setosa']
['5.8', '4', '1.2', '0.2', 'setosa']
在上面的代码中,row将会是一个列表。因此,需要通过索引访问其中的每一个元素。
由于这样的索引常常容易混淆,可以将数据读取为字典。示例如下:
代码语言:javascript复制with open('iris.csv') as f:
f_csv = csv.DictReader(f)
for row in f_csv:
print(row)
输出内容:
代码语言:javascript复制{'Sepal.Length': '5.1', 'Sepal.Width': '3.5', 'Petal.Length': '1.4', 'Petal.Width': '0.2', 'Species': 'setosa'}
{'Sepal.Length': '4.9', 'Sepal.Width': '3', 'Petal.Length': '1.4', 'Petal.Width': '0.2', 'Species': 'setosa'}
{'Sepal.Length': '4.7', 'Sepal.Width': '3.2', 'Petal.Length': '1.3', 'Petal.Width': '0.2', 'Species': 'setosa'}
{'Sepal.Length': '4.6', 'Sepal.Width': '3.1', 'Petal.Length': '1.5', 'Petal.Width': '0.2', 'Species': 'setosa'}
{'Sepal.Length': '5', 'Sepal.Width': '3.6', 'Petal.Length': '1.4', 'Petal.Width': '0.2', 'Species': 'setosa'}
{'Sepal.Length': '5.4', 'Sepal.Width': '3.9', 'Petal.Length': '1.7', 'Petal.Width': '0.4', 'Species': 'setosa'}
{'Sepal.Length': '4.6', 'Sepal.Width': '3.4', 'Petal.Length': '1.4', 'Petal.Width': '0.3', 'Species': 'setosa'}
{'Sepal.Length': '5', 'Sepal.Width': '3.4', 'Petal.Length': '1.5', 'Petal.Width': '0.2', 'Species': 'setosa'}
{'Sepal.Length': '4.4', 'Sepal.Width': '2.9', 'Petal.Length': '1.4', 'Petal.Width': '0.2', 'Species': 'setosa'}
{'Sepal.Length': '4.9', 'Sepal.Width': '3.1', 'Petal.Length': '1.5', 'Petal.Width': '0.1', 'Species': 'setosa'}
{'Sepal.Length': '5.4', 'Sepal.Width': '3.7', 'Petal.Length': '1.5', 'Petal.Width': '0.2', 'Species': 'setosa'}
{'Sepal.Length': '4.8', 'Sepal.Width': '3.4', 'Petal.Length': '1.6', 'Petal.Width': '0.2', 'Species': 'setosa'}
{'Sepal.Length': '4.8', 'Sepal.Width': '3', 'Petal.Length': '1.4', 'Petal.Width': '0.1', 'Species': 'setosa'}
这样循环中的 row 即为一个字典,其键为表头,值为每一行中各列的值。
要写入 CSV 数据,也可以使用 csv 模块来完成,但是要创建一个写入对象。
代码语言:javascript复制with open('iris.csv') as f:
f_csv = csv.writer(f)
f_csv.writerow(headers)
f_csv.writerows(rows)
如果数据是字典,那么可以这样做:
代码语言:javascript复制with open('iris.csv') as f:
f_csv = csv.DictWriter(f, headers)
f_csv.writeheader()
f_csv.writerows(rows)
讨论
你应该总是使用 csv 模块来处理,而不是自己手动分解和解析 CSV 数据。比如,许多人倾向于写出这样的代码:
代码语言:javascript复制with open('iris.csv') as f:
for line in f:
row = line.split(',')
# process row
...
很多时候,生物信息的数据文件是以 tab 键分隔的,可以使用下面的代码:
代码语言:javascript复制with open('iris.tsv') as f:
f_tsv = csv.reader(f, delimiter = 't')
for row in f_tsv:
print(row)
输出内容:
代码语言:javascript复制['Sepal.Length', 'Sepal.Width', 'Petal.Length', 'Petal.Width', 'Species']
['5.1', '3.5', '1.4', '0.2', 'setosa']
['4.9', '3', '1.4', '0.2', 'setosa']
['4.7', '3.2', '1.3', '0.2', 'setosa']
['4.6', '3.1', '1.5', '0.2', 'setosa']
['5', '3.6', '1.4', '0.2', 'setosa']
['5.4', '3.9', '1.7', '0.4', 'setosa']
['4.6', '3.4', '1.4', '0.3', 'setosa']
['5', '3.4', '1.5', '0.2', 'setosa']
最后,如果我们的目标是通过读取 CSV 数据来进行数据分析和统计,那么应该考虑 Pandas 这个 Python 库。它有一个方便的函数 pandas.read_csv(),能够将 CSV 数据加载到 DataFrame 对象中。之后,就可以生成各种各样的统计摘要了,还可以对数据进行筛选并执行其他类型的高级操作。
参考
- 《Python Cookbook》第三版
- http://python3-cookbook.readthedocs.org/zh_CN/latest/