Python在生物信息学中的应用:读写表格文件

2024-02-21 16:27:45 浏览数 (2)

许多生物信息学数据都存储在文本文件中, 每行一条记录,列之间用逗号(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/

0 人点赞