2014-07-23 16 views
5

Bölgelere ait bir DataFrame (başlangıç, bitiş) koordinatları ve belirli bir bölgeye girebilecek veya düşmeyecek başka bir DataFrame'inizin olduğunu varsayalım. Örneğin: Her konumu, herhangi bir durumda olabilir, ancak bir bölgede maksimum içine düşmesi sağlanırÇoklu sütunlardaki ilişkiye dayalı pandalar veri çerçevesinin birleştirilmesi

position['BP'] >= region['start'] & 
position['BP'] <= region['end'] & 
position['chromosome'] == region['chromosome'] 

:

region = pd.DataFrame({'chromosome': [1, 1, 1, 1, 2, 2, 2, 2], 'start': [1000, 2000, 3000, 4000, 1000, 2000, 3000, 4000], 'end': [2000, 3000, 4000, 5000, 2000, 3000, 4000, 5000]}) 
position = pd.DataFrame({'chromosome': [1, 2, 1, 3, 2, 1, 1], 'BP': [1500, 1100, 10000, 2200, 3300, 400, 5000]}) 
print region 
print position 


    chromosome end start 
0   1 2000 1000 
1   1 3000 2000 
2   1 4000 3000 
3   1 5000 4000 
4   2 2000 1000 
5   2 3000 2000 
6   2 4000 3000 
7   2 5000 4000 

     BP chromosome 
0 1500   1 
1 1100   2 
2 10000   1 
3 2200   3 
4 3300   2 
5 400   1 
6 5000   1 

bir konum eğer bir bölge içine düşmektedir.

Bu iki veri çerçevesini birleştirmek için en iyi yol hangisi olursa olsun, herhangi bir bölgeye düşerse, bulunduğu yere göre ek sütunlar ekleyecektir. Bu durumda verilmesi kabaca aşağıdaki çıkışı:

def within(pos, regs): 
    istrue = (pos.loc['chromosome'] == regs['chromosome']) & (pos.loc['BP'] >= regs['start']) & (pos.loc['BP'] <= regs['end']) 
    if istrue.any(): 
     ind = regs.index[istrue].values[0] 
     return(regs.loc[ind ,['start', 'end']]) 
    else: 
     return(pd.Series([None, None], index=['start', 'end'])) 

position[['start', 'end']] = position.apply(lambda x: within(x, region), axis=1) 
print position 

     BP chromosome start end 
0 1500   1 1000 2000 
1 1100   2 1000 2000 
2 10000   1 NaN NaN 
3 2200   3 NaN NaN 
4 3300   2 3000 4000 
5 400   1 NaN NaN 
6 5000   1 4000 5000 

Ama I:

 BP chromosome start end 
0 1500   1 1000 2000 
1 1100   2 1000 2000 
2 10000   1 NA  NA 
3 2200   3 NA  NA 
4 3300   2 3000 4000 
5 400   1 NA  NA 
6 5000   1 4000 5000 

Bir yaklaşım aşağıdaki gibi DataFrame.apply yöntemi kullanmak sonra istediğim ilişkiyi hesaplamak için bir işlev yazmak ve etmektir O (N) zamanındaki her karşılaştırmayı yapmaktan daha iyi bir yol olduğunu umuyorum. Teşekkürler!

cevap

5

bir çözüm yapmak olacaktır bir iç birleşim position ile katılmak sol do ardından ihlal satırlarını hariç, chromosome üzerine ve: başıma bu sorunu çözmek için bulundu

>>> df = pd.merge(position, region, on='chromosome', how='inner') 
>>> idx = (df['BP'] < df['start']) | (df['end'] < df['BP']) # violating rows 
>>> pd.merge(position, df[~idx], on=['BP', 'chromosome'], how='left') 
     BP chromosome end start 
0 1500   1 2000 1000 
1 1100   2 2000 1000 
2 10000   1 NaN NaN 
3 2200   3 NaN NaN 
4 3300   2 4000 3000 
5 400   1 NaN NaN 
6 5000   1 5000 4000 
+0

Bu kesinlikle performansı artırır. Teşekkürler! – dylkot

+0

Maalesef veri dosyam, bellekte df tutmak için çok büyük. Konum ve bölgeyi dış indeks olarak kromozomlu çok endeksli veri çerçevelerine yüklediğimde ve her kromozom için bağımsız olarak birleştiğim alternatif bir çözüm bulmaya çalışıyorum. Şimdi bu kodu çalışıyorum ama eğer bunu daha iyi bir şekilde görüyorsa, lütfen bana bildirin. Teşekkürler. – dylkot

0

iyi yolu Büyük veri setleri, python ile pitotole (http://pythonhosted.org/pybedtools/) sarılmış olan yatak takımlarının kesişim yöntemini kullanmaktaydı çünkü problem, iki grup bölgeye (bu durumda bir tanesi sadece 1 uzunluğuna ait) müdahale etmek için aşağı doğru kaymaktadır.

İlgili konular