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