블록에 누락된 데이터 삽입

블록에 누락된 데이터 삽입

저는 생물학자이고 이 문제를 해결하려고 노력 중입니다. 어디서부터 시작해야 할지 안내해 주세요. 어느 포럼에 게시해야 할지 모르겠습니다. 이곳이 올바른 장소가 아닌 경우 알려주시기 바랍니다.

엄격하게 두 가지 소스 또는 여러 소스의 혼합이 될 수 있는 일부 값 블록이 있습니다.

'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 }

때로는 내 데이터에 하나 또는 두 개의 소스가 누락되는 경우가 있습니다. 이 경우 누락된 소스 값을 삽입하고 싶습니다.

블록 내에서 Source1이 누락되고 Source2가 누락되고 XX혼합된 값 중 하나가 YY이면 Source1이 임을 알 수 있습니다 YY. 또 다른 예는 블록에서 Source1이 누락되고 Source2가 누락되었으며 XX혼합 값 중 하나가 XY이면 Source1은 입니다 YY. 보시다시피, 혼합물 세트에 존재하는 내용을 기반으로 소스를 이해하는 두 가지 방법이 있습니다.

두 소스 모두 존재하지 않지만 블록에 혼합된 값 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

더 쉬운 방법으로 할 수 있을 것 같지만, 한 시간 동안 고민한 끝에 제가 생각해 낼 수 있는 최선의 방법은 다음과 같습니다.이 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에는 있어야 함).

관련 정보