Python 基于AWK创建反向补码序列
亲爱的stackoverflow用户: 我有如下选项卡sep数据:Python 基于AWK创建反向补码序列,python,awk,Python,Awk,亲爱的stackoverflow用户: 我有如下选项卡sep数据: head -4 input.tsv seq A C change seq T A ok seq C C change seq AC CCT change 我需要在awk中创建反向补码函数,这样做 head -4 output.tsv seq T G change seq T A ok seq G G change seq GT AGG change aw
head -4 input.tsv
seq A C change
seq T A ok
seq C C change
seq AC CCT change
我需要在awk中创建反向补码函数,这样做
head -4 output.tsv
seq T G change
seq T A ok
seq G G change
seq GT AGG change
awk 'BEGIN {c["A"] = "T"; c["C"] = "G"; c["G"] = "C"; c["T"] = "A" }{OFS="\t"}
function revcomp( i, o) {
o = ""
for(i = length; i > 0; i--)
o = o c[substr($0, i, 1)]
return(o)
}
{
if($4 == "change"){$2 = revcom(); $3 = revcom()} print $0; else print $0}' input
所以,如果第四列标记为“change”,我需要创建反向补码序列
提示-在bash中执行相同的操作,例如tr
,bash此任务的一行代码是:
echo "ACCGA" | rev | tr "ATGC" "TACG"
A => T
C => G
G => C
T => A
ACCATG => CATGGT
我被试过这样的事
head -4 output.tsv
seq T G change
seq T A ok
seq G G change
seq GT AGG change
awk 'BEGIN {c["A"] = "T"; c["C"] = "G"; c["G"] = "C"; c["T"] = "A" }{OFS="\t"}
function revcomp( i, o) {
o = ""
for(i = length; i > 0; i--)
o = o c[substr($0, i, 1)]
return(o)
}
{
if($4 == "change"){$2 = revcom(); $3 = revcom()} print $0; else print $0}' input
生物反向序列平均值:
echo "ACCGA" | rev | tr "ATGC" "TACG"
A => T
C => G
G => C
T => A
ACCATG => CATGGT
和反向补码的意思是:
echo "ACCGA" | rev | tr "ATGC" "TACG"
A => T
C => G
G => C
T => A
ACCATG => CATGGT
编辑:任何仅供教育的人都可以在python中共享此解决方案。请尝试以下内容,并使用显示的示例编写和测试(在GNU
awk
中)
awk'
开始{
标签[“A”]=“T”
标签[“C”]=“G”
标签[“G”]=“C”
标签[“T”]=“A”
}
函数cVal(字段){
删除数组
num=拆分($field,array,“”)
对于(k=1;k,只需稍微修改一下尝试,您就可以执行以下操作
function revcomp(arg) {
o = ""
for(i = length(arg); i > 0; i--)
o = o c[substr(arg, i, 1)]
return(o)
}
BEGIN {c["A"] = "T"; c["C"] = "G"; c["G"] = "C"; c["T"] = "A" ; OFS="\t"}
{
if($4 == "change") {
$2 = revcomp($2);
$3 = revcomp($3)
}
}1
这里的关键是使用函数revcomp
将参数作为列值,并通过从末尾迭代对其进行操作。您以前在整行$0
,即substr($0,i,1)
,这将导致对数组c
进行大量异常查找
我还随意更改了函数的原型revcomp
,以获取输入字符串并返回反向字符串。因为我不确定您在最初尝试中打算如何使用
如果您打算在较大脚本的一部分中使用上述内容,我建议将上述整个代码放在脚本文件中,将she bang解释器设置为#!/usr/bin/awk-f
,并以awk-f script.awk input.tsv
的形式运行脚本
在awk
中实现的粗糙bash版本如下所示。请注意,它不是干净的,也不是推荐的方法。请参阅
与前面一样,将函数调用为$2=revcomp\u bash($2)
和$3=revcomp\u bash($3)
您的整个代码都讲GNUawk
-ism,因此不想将其转换为与POSIX兼容的代码。您可以使用带有空的反限制器的split()
,而不是length()
,但是POSIX规范很高兴地说“空字符串作为fs值的效果是未指定的。”对于这个特定的应用程序来说效率有点低,因为它在每次调用tr()
时都会创建映射数组,并在tr()
中执行相同的循环,然后在rev()
中再次执行相同的循环,但我想展示一下如何编写独立的tr()
和rev()
功能强大,而且速度可能足以满足您的需求:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
$4 == "change" {
for ( i=2; i<=3; i++) {
$i = rev(tr($i,"ACGT","TGCA"))
}
}
{ print }
function tr(instr,old,new, outstr,pos,map) {
for (pos=1; pos<=length(old); pos++) {
map[substr(old,pos,1)] = substr(new,pos,1)
}
for (pos=1; pos<=length(instr); pos++) {
outstr = outstr map[substr(instr,pos,1)]
}
return outstr
}
function rev(instr, outstr,pos) {
for (pos=1; pos<=length(instr); pos++) {
outstr = substr(instr,pos,1) outstr
}
return outstr
}
如果您对perl
没有异议:
$ perl -F'\t' -lane 'if($F[3] eq "change") {
$F[1] = (reverse $F[1] =~ tr/ATGC/TACG/r);
$F[2] = (reverse $F[2] =~ tr/ATGC/TACG/r) }
print join "\t", @F' ip.txt
seq T G change
seq T A ok
seq G G change
seq GT AGG change
也可以使用,但这不是特定于列的,将更改ATCG
字符的任何序列:
perl -lpe 's/\t\K[ATCG]++(?=.*\tchange$)/reverse $&=~tr|ATGC|TACG|r/ge'
OP表示如果第4列标记为“更改”@oguzismail,现在做了更改,谢谢你让我知道。@RavinderSingh13谢谢你非常及时的回答-我将尝试测试你的解决方案!@Geroge,我当然也在这里添加了详细的级别解释,以防我在这里遇到任何疑问。谢谢你的回答。可能是愚蠢的问题,但我没有看到任何“awk”关于脚本的开始?@ Geroge:只使用“代码> AWK……”输入的全部片段。TSV 这是绝对完美的解决方案,看起来非常有效!非常感谢!!您的代码是POSIX兼容的,没有GNUISS。您应该考虑的一个调整是:<代码> ReVCOMP(ARG)< /代码>应该是代码> ReVCOMP(ARG,I,O)
因此,i
和o
是函数局部变量,与代码中其他地方或第二次调用该代码时的值无关。如果这样做,则不需要o=”“
。