2013-08-28 97 views
3

我正在尋找一個數據結構來表示一些遺傳數據。該數據可以表示爲大小爲n的列表,其中每個條目還具有在0和1之間的實數的「遺傳位置」。爲了使命名清晰,我將稱爲列表id中的位置,並且遺傳位置gpos。我實施這種方式是作爲一類與自定義索引的數據結構

class Coords(object): 

    def __init__(self, *args, **kwargs): 
     self.f = list(*args, **kwargs) 
     self.r = dict() 
     for i,e in enumerate(self.f): 
      self.r[e] = i 

    def __setitem__(self,x,y): 
     self.f.__setitem__(x,y) 
     self.r.__setitem__(y,x) 

    def __getitem__(self,x): 
     return self.f.__getitem__(x) 

    def __len__(self): 
     return self.f.__len__() 

現在,我有兩個問題與此。第一個是self.r的indeces是浮動的,這顯然是一個壞主意。我正在考慮將它們轉換爲字符串(具有固定的數字位數),但是有更好的主意嗎?另一個問題我已經是我想要實現通過gpos訪問的條目,所以如果我舉個例子,想gpos 0.2和0.4之間的訪問一切,我希望能夠做到這一點使用

import numpy as np 
Coords(np.arange(1,0,-.1)) 
c.r[0.2:0.4] 

有沒有簡單的方法來定義?我正在考慮使用二進制搜索找到正確的id的起始和結束位置,然後使用這些ID訪問self.f,但有沒有一種方法可以實現上述語法?

回答

5

當您用切片索引對象時,Python會用您提供的輸入創建一個slice對象。例如,如果您執行c[0.2:0.4],則傳遞給c.__getitem__的參數將爲slice(0.2, 0.4)。所以,你可以有這樣的事情代碼在你__getitem__方法:

def __getitem__(self, x): 
    if isinstance(x, slice): 
     start = x.start 
     stop = x.stop 
     step = x.step 
     # Do whatever you want to do to define your return 
    ... 

如果你想在Coords對象上不能使用這個花哨的索引,但在self.r字典,我認爲最簡單的是創建一個FancyIndexDictdict的子類,修改其__getitem__方法,然後使self.rFancyIndexDict,而不是dict

+2

這很酷,我沒有不知道切片符號接受了非int參數! – lmjohns3

+0

直到我試着寫這個答案時,我都沒有... – Jaime

+1

其實我只是嘗試過其他數據類型,它似乎基本上任何表達式都可以工作,甚至瘋狂像'fancy_obj ['a':('b',8 )]' – lmjohns3

3

如果您知道您的gpos值將(或可以)始終按排序順序存儲,那麼我肯定會推薦使用二進制搜索來執行此任務。您可以利用數組語法和numpy的內置實現與searchsorted

>>> gpos_vals = np.linspace(0, 1, 11) 
>>> gpos_vals 
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]) 
>>> lo, hi = gpos_vals.searchsorted([0.22, 0.52]) 
>>> lo, hi 
(3, 6) 
>>> gpos_vals[lo:hi] 
array([ 0.3, 0.4, 0.5]) 

我覺得這很好地避免了您指出了使用的float字典鍵,這可能是有問題的有關問題。

您還可以結合這個答案與海梅的和做的一類,以查找自定義__getitem__內切片,然後通過切片參數searchsorted在我的代碼片段:

class GeneticPositions(object): 
    def __init__(self, gpos_values): 
     self.gpos_values = np.asarray(gpos_values) 

    def __getitem__(self, x): 
     if isinstance(x, slice): 
      lo, hi = self.gpos_values.searchsorted(
       [x.start or 0, x.stop or 1]) 
      return self.gpos_values[lo:hi] 
     return self.gpos_values[x] 
+0

不錯!在調用'np.searchsorted'之前,你實際上必須在'x.start'和'x.stop'的值中檢查'None':一部分'[:0.3]'將'.start'設置爲'None '(和往常一樣''和'.stop'到'0.3')。 – Jaime

+0

@Jaime很好抓! – lmjohns3