ブロックに欠落しているデータを挿入する

ブロックに欠落しているデータを挿入する

私は生物学者であり、この問題を解決しようとしています。どこから始めるべきかをご案内ください。どのフォーラムに投稿するのかわかりません。ここが正しい場所ではない場合は、お知らせください。

厳密には、2つのソースまたは複数のソースを混在させることができるいくつかの値ブロックがあります。

'source1', 'source2' and 'mixture'実際のデータのキーワードです。

収集に制限されたソース値{ AA, TT, GG , CC }

ブレンド値はコレクション内で制限されますが、{ AA , TT , GG , CC , AT , AG, AC , TG , TC , GC } ブレンド値は同じブロック内のソースによって異なります。だからblockNの中にいるなら、

 source1 =XX  where X~{A,T,G,C}



source2 =YY  where Y~{A,T,G,C}

その後、混合値は次の位置になければなりません。{ XX, YY, XY }

時々、私のデータに1つまたは2つのソースがありません。この場合、欠落しているソース値を挿入したいと思います。

ブロック内でSource1が欠落しており、Source2が欠落しており、XX混合値の1つがあるYY場合、Source1が存在することがわかりますYY。別の例は、ブロック内のSource1が欠落しており、Source2が欠落しており、XX混合値の1つがXYある場合、Source1はですYY。ご覧のとおり、混合セットに存在する内容に基づいてソースを理解するには2つの方法があります。

両方のソースは存在しませんが、ブロックに混合された値XYが存在する状況がある可能性があります。これは、Source1とSource2がXXとYYであることを示します(またはYY and XX順序は重要ではありません)。

私のサンプルデータ

block1 source1 AA 
block1 source2 TT
block1 mixture AT
block1 mixture AA
block1 mixture TT

block2 source1 GG
block2 source2 TT
block2 mixture TG
block2 mixture TG
block2 mixture TT

block3 source1 AA
block3 source2 TT
block3 mixture AT
block3 mixture AA
block3 mixture TT

block4 mixture AT
block4 mixture AA
block4 mixture TT

block5 source2 TT
block5 mixture TG
block5 mixture TG

私が望む出力は

block1 source1 AA 
block1 source2 TT
block1 mixture AT
block1 mixture AA
block1 mixture TT

block2 source1 GG
block2 source2 TT
block2 mixture TG
block2 mixture TG
block2 mixture TT

block3 source1 AA
block3 source2 TT
block3 mixture AT
block3 mixture AA
block3 mixture TT

block4 source1 AA
block4 source2 TT
block4 mixture AT
block4 mixture AA
block4 mixture TT


block5 source1 GG
block5 source2 TT
block5 mixture TG
block5 mixture TG

ブロック4と5に挿入された内容を参照してください。理解しやすくするために、これらの塊を区別しました。実際のデータでは空行で区切られません。

ベストアンサー1

より簡単な方法でできると思いますが、1時間悩んだ末に私が思い出せる最善の方法は次のとおりです。このPythonスクリプト:

#! /usr/bin/env python3

import sys, os

class Block:
    block_id = ''
    source1 = ''
    source2 = ''
    mixtures = []
    def __init__(self, block_id = '', source1 = '', source2 = '', mixtures = []):
        self.block_id = block_id
        self.mixtures = mixtures
        self.source1 = source1
        self.source2 = source2

        # Convert mixtures to a set of characters. For example, 
        #     ''.join(["AT", "TT"]) 
        # creates the string "ATTT". set() then converts that string to 
        # a set of characters {'A', 'T'}
        sources = set(''.join(mixtures))

        # If a source is empty, we take from the set the first element (pop()) 
        # after removing the other source (difference()). Since the set 
        # contains single characters, we double it to get "AA", "TT", etc.
        if self.source1 == '':
            self.source1 = sources.difference(set(self.source2)).pop()*2
        sources.remove (self.source1[0])
        if self.source2 == '':
            self.source2 = sources.pop()*2

    def print (self):
        print (self.block_id, "source1", self.source1)
        print (self.block_id, "source2", self.source2)
        for mix in self.mixtures:
            print (self.block_id, "mixture", mix)

if len(sys.argv) == 1:
    files = [os.stdin]
else:
    files = (open(f) for f in sys.argv[1:])

for f in files:
    # Read in all the lines
    data = [line for rawline in f for line in [rawline.strip().split(' ')]]
    # Get the unique block IDs
    blocks = set (lines[0] for line in data)
    # For each block ID
    for b in blocks:
        # The corresponding mixtures
        mix = [line[2] for line in data if line[0] == b and "mixture" == line[1]]

        # If "source1 XX" is present, we will get the list ['XX'], and [] if 
        # source1 is not present. ''.join() allows us to flatten ['XX']  to 
        # just 'XX' (and doesn't affect []). Similarly for source2.
        source1 = ''.join(d[2] for line in data if line[0] == b and "source1" == line[1])
        source2 = ''.join(d[2] for line in data if line[0] == b and "source2" == line[1])

        # Create an object of the class defined above, and print it.
        # Initialization fills up the blank values.
        Block(b, source1, source2, mix).print()

それでも、これは順序付けされていないランダムな出力を提供します(つまり、block3データが前に来ることがあるblock1など)。

これをスクリプト(たとえばinsert.py)に保存し、次のコマンドを実行します。

python3 insert.py inputfile

私はこれを書き直しましたアッ:

#! /usr/bin/awk -f

function build (block, source1, source2, sources, mixtures)
{       
    if (! source1)
    {
        for (char in sources)
        {
            if (source2 != char char)
            {
                source1 = char char
                delete sources[char]
                break
            }
        }
    }
    if (! source2)
    {   
        for (char in sources)
        {
            if (source1 != char char)
            {
                source2 = char char
                delete sources[char]
                break
            }
        }
    }
    printf "%s %s %s\n", block, "source1", source1
    printf "%s %s %s\n", block, "source2", source2
    for (m in mixtures)
    {
        for (i = 0; i < mixtures[m]; i++)
        {
            printf "%s %s %s\n", block, "mixture", m
        }
    }

}

{
    if (prev != $1)
    {
        if (prev in data)
        {
            build(prev, source1, source2, sources, mixtures)
        }

        prev = $1
        source1 = ""
        source2 = ""
        delete sources
        delete mixtures
    }

    data[$1]++
    if ($2 == "source1") {source1 = $3; next}
    if ($2 == "source2") {source2 = $3; next}
    if ($2 == "mixture")
    {
        mixtures[$3]++ 
        split ($3, chars, "")
        for (i=1; i <= length($3); i++)
        {
            sources[chars[i]]++
        }
    }
}

END { build(prev, source1, source2, sources, mixtures) }

スクリプト(たとえばinsert.awk)に保存chmod +xして実行します。

./insert.awk inputfile

これでコマンドも維持する必要があります。を使用しましたが、delete一部のawkにはない可能性があります(ただし、GNU awkとmawkには必要です)。

おすすめ記事