0

我有一个 CSV 文件,我想从中提取列,但只能从某些行中提取。它看起来像这样:

gene_id, ENSDARG00000104632, gene_version, 2, gene_name, RERG

gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186

gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186

gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186

gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186

本质上,我想要第 2 列和第 6 列,但仅来自第 5 列中具有“gene_name”的行。所以我想提取:

ENSDARG00000104632, RERG

(它从那里继续,有数千行)

这是我写的:

import csv


with open('filename.csv', 'rb') as infh:
        reader = csv.reader(infh)
        for row in reader:
                if row[4] == 'gene_name':
                        print row[1, 5]

但是,它给了我这个错误:

IndexError 中的文件“./gene_name_grabber.sh”第 10 行 if row[4] == 'gene_name'::列表索引超出范围

我了解此错误意味着我已要求它查看大于行中索引数的索引号......但每行中显然有超过 4 个索引。请帮忙?

谢谢!

4

3 回答 3

1

显然,有些行不包含足够的列。试试这个:

import csv

with open('input.csv', 'r') as f:

    reader = csv.reader(f)

    for row in reader:
        try:
            if 'gene_name' in row[4]:
                print('%s, %s' % (row[1].strip(), row[5].strip()))
        except IndexError:
            continue

...输出:

ENSDARG00000104632, RERG

于 2017-09-21T22:57:16.840 回答
0

我想要第 2 列和第 6 列,但仅来自第 5 列中具有“gene_name”的行。

我爱蟒蛇。但这最自然地表示为

awk '$5 ~ /gene_name/ {print $2, $6}'

让我们回到python。这不是你想写的:

                    print row[1, 5]

改为print(row[1], row[5])改为。

您的某些行只有少量列。因此,您需要包装 eg 的取消引用row[4]row[5]if验证它是否足够长的行的语句中:

    if len(row) > 5:
        ...
于 2017-09-21T22:55:34.253 回答
0

正如 Antimony 所指出的,听起来您的数据中偶尔会出现缺失值,而 csv 无法轻松处理开箱即用的情况。我建议使用像 pandas 这样的库,它有一个read_csv函数,可以处理缺失值。以此数据为例:

gene_id, ENSDARG00000104632, gene_version, 2, gene_name, RERG
gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186
gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186
gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186
gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186
gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186
gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186
gene_id, ENSDARG00000104632, gene_version, 2, transcript_id,
gene_id, ENSDARG00000104632, gene_version, , transcript_id,
gene_id, ENSDARG00000104632, gene_version, 2, transcript_id, ENSDART00000166186

可以读作如下:

import pandas as pd

# Use the 2nd, 5th and 6th columns - i.e.column indices 1, 4 and 5 respectively
# And, we set the 'not available' data - i.e. `na_values` as 'N/A'.
data = pd.read_csv('test.dat', na_values='N/A', header=None, skipinitialspace=True, usecols=[1,4,5])

# now select only the rows without 'gene_version':
d = data.loc[data[4] != 'gene_name']

# and, now we only select columns with index 1 and 5:
selected_data = d[[1, 5]]

产量:

                    1                   5
0  ENSDARG00000104632                RERG
1  ENSDARG00000104632  ENSDART00000166186
2  ENSDARG00000104632  ENSDART00000166186
3  ENSDARG00000104632  ENSDART00000166186
4  ENSDARG00000104632  ENSDART00000166186
5  ENSDARG00000104632  ENSDART00000166186
6  ENSDARG00000104632  ENSDART00000166186
7  ENSDARG00000104632                 NaN
8  ENSDARG00000104632                 NaN
9  ENSDARG00000104632  ENSDART00000166186

如预期的。

但是,如果缺少数据 - 就像在这个例子中一样 - 你所要做的就是删除这些行,如:

selected_data.dropna()

哪个输出:

                    1                   5
1  ENSDARG00000104632  ENSDART00000166186
2  ENSDARG00000104632  ENSDART00000166186
3  ENSDARG00000104632  ENSDART00000166186
4  ENSDARG00000104632  ENSDART00000166186
5  ENSDARG00000104632  ENSDART00000166186
6  ENSDARG00000104632  ENSDART00000166186
9  ENSDARG00000104632  ENSDART00000166186

(但是,这可能不是您想要的。)

参考

https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html

于 2017-09-21T23:06:08.910 回答