2013-05-02 58 views
4

我得到我的脚湿一些基因组分析筛选高于阈值和我有点卡住了。我有一些非常稀疏的数据,需要找到移动平均值超过某个阈值的位置,并将每个点标记为1或0.数据是唯一类型,因此我无法使用可用的程序进行分析。有效地采取稀疏数据的移动平均线和蟒蛇

每个点表示对人类基因组的一个点(碱基对)。对于每个数据集,都有200,000,000个潜在点。数据本质上是一个约12000个索引/值对的列表,其中所有其他点都假定为零。我需要做的是在整个数据集中取一个移动平均值,并返回平均值超过阈值的区域。

我目前正在读的数据集顺序每一点和周围的建筑,我觉得每一个点的数组,但这是大窗口大小很慢。有没有更高效的方法来做到这一点,也许有scipy或pandas?

编辑:下杰米的魔码的伟大工程(但我无法给予好评还)!我非常感激。

+0

也许将数据转换为可用程序可以理解的格式会更有意义。数据转换最可能比复杂分析和结果可视化更容易实现。 – Wilbert 2013-05-02 08:44:03

回答

3

你可以用numpy向量化整个事物。我已经建立的该随机数据集(近似)12000个索引0和199999999,和随机浮点数的0和1之间在同样长的列表之间:

indices = np.unique(np.random.randint(2e8,size=(12000,))) 
values = np.random.rand(len(indices)) 

然后我构建总窗口大小2*win+1的索引数组围绕每个indices,以及多少有助于通过该点的移动平均的对应阵列的:

win = 10 

avg_idx = np.arange(-win, win+1) + indices[:, None] 
avg_val = np.tile(values[:, None]/(2*win+1), (1, 2*win+1)) 

所有剩下是搞清楚重复指数和增加的贡献的移动平均值一起:

unique_idx, _ = np.unique(avg_idx, return_inverse=True) 
mov_avg = np.bincount(_, weights=avg_val.ravel()) 

您现在可以得到指数在其中,例如列表移动平均超过0.5时,如:

unique_idx[mov_avg > 0.5] 

至于性能,第一次打开上述代码到一个函数:

def sparse_mov_avg(idx, val, win): 
    avg_idx = np.arange(-win, win+1) + idx[:, None] 
    avg_val = np.tile(val[:, None]/(2*win+1), (1, 2*win+1)) 
    unique_idx, _ = np.unique(avg_idx, return_inverse=True) 
    mov_avg = np.bincount(_, weights=avg_val.ravel()) 
    return unique_idx, mov_avg 

这里有一些定时几个窗口大小,对所描述的测试数据在开始处:

In [2]: %timeit sparse_mov_avg(indices, values, 10) 
10 loops, best of 3: 33.7 ms per loop 

In [3]: %timeit sparse_mov_avg(indices, values, 100) 
1 loops, best of 3: 378 ms per loop 

In [4]: %timeit sparse_mov_avg(indices, values, 1000) 
1 loops, best of 3: 4.33 s per loop 
+0

感谢您花时间真正思考这个问题。大部分代码对我来说都是陌生的,因为我没有太多地使用numpy,所以这非常有帮助。当你想出这么好的解决方案时,我觉得我浪费了很多时间来处理这个问题! – 2013-05-03 01:05:27

+0

我发现,增加窗口大小大于约100导致内存错误:( – 2013-05-03 08:34:01

+0

@MarkB这并没有太大的意义。随着号码,你所提供的移动平均线就只能是几百万的数组条目 – Jaime 2013-05-03 14:12:49