提取numpy结构化数组的最高值

时间:2013-07-16 21:08:35

标签: python arrays parsing numpy

我有一个名为“data”的结构化数组,对同一个条目有几个分数。为了这个问题,我将“数据”减少到以下2列。

queryid    bitscore
gene1      500
gene1      480
gene1      440
gene2      900
gene2      300

我想要做的是为queryid提取相同的最高值,即bitscore比最高位核低至少10%的任何公共条目。

例如,只有前两个条目“gene1”应该保守,因为第三个条目的位数低于500的10%。对于基因2,只应保留第一个(这一个很容易)。

queryid    bitscore
gene1      500
gene1      480
gene2      900

当我像这样做一个循环时:

for i in range(0, lastrow-1, 1):
if data[i]['queryid'] == data[i+1]['queryid']:
    if data[i+1]['bitscore'] < data[i]['bitscore']-(0.01*data[i]['bitscore']):
       data[i+1]['queryid'] = 'DELETE'

data = data[data[:]['queryid'] != 'DELETE']

所有“gene1”条目都将被保留,因为440在480的10%范围内。

我可以将最高价值添加到另一个可以作为参考的列,但我想检查一下你们是否对它有更好的了解......

3 个答案:

答案 0 :(得分:3)

如果你能够使用pandas,那就会成为一个问题:

from pandas import DataFrame
import numpy as np

# Taken from Theodros
data = zip(('gene1',) * 3 + ('gene2',) * 2, [500, 480, 440, 900, 300])
dtype = [('queryid', 'S6'), ('bitscore', 'i4')]
struct_arr = np.array(data, dtype=dtype)

# Create pandas DataFrame from NumPy struct array
df = DataFrame.from_records(struct_arr)

# Filter the rows per group
df.groupby('queryid').apply(lambda x: x[x["bitscore"] >= x["bitscore"].max() * 0.9])

产地:

          queryid  bitscore
queryid                    
gene1   0   gene1       500
        1   gene1       480
gene2   3   gene2       900

答案 1 :(得分:2)

使用逻辑索引可能比for循环快得多。这样的事情怎么样:

def high_bitscores(a,qid,thresh=0.9):
    valid = a[a['queryid'] == qid]
    return valid[valid['bitscore'] >= valid['bitscore'].max()*thresh]

修改:如果您要返回data中传递此条件的所有元素,您可以循环显示唯一的queryiddata并更新一组布尔索引,指定哪些元素通过测试:

def all_high_bitscores(a,thresh=0.9):

    # set of indices for the elements in a that we're going to keep
    keep = np.zeros(a.size,np.bool)

    for qid in set(a['queryid']):
        idx = a['queryid'] == qid
        keep[idx] = a[idx]['bitscore'] >= a[idx]['bitscore'].max()*thresh

    return a[keep]

答案 2 :(得分:1)

您可以使用itertools.groupby来迭代具有相同queryid的块。然后,您可以过滤掉阈值以下的记录。在此步骤中,您将保留numpy.structured_array数据结构并处理单个元组。通过将filter定义为生成器,您可以从过滤器输出中动态构建新的结构化数组。

from itertools import groupby
from operator import itemgetter


def filter(struct_arr, threshold):
    for k, g in groupby(struct_arr, key=itemgetter(0)):
        ref = g.next()
        yield ref
        ref = ref[1]
        for e in g:
            if (float(e[1]) / ref) < threshold:
                break
            yield e

示例:

data = zip(('gene_1',) * 3 + ('gene_2',) * 2, [500, 480, 440, 900, 300])
dtype = [('query_id', 'S6'), ('bitscore', 'i4')]
struct_arr = np.array(data, dtype=dtype)


np.fromiter(filter(struct_arr), dtype=dtype)

给出了

array([('gene_1', 500), ('gene_1', 480), ('gene_2', 900)], 
      dtype=[('query_id', 'S6'), ('bitscore', '<i4')])