美文网首页宏基因组
2020-07-03 常用有趣命令之数据处理

2020-07-03 常用有趣命令之数据处理

作者: 阿乜太帅 | 来源:发表于2020-07-03 19:07 被阅读0次
    1. 第一列相同时数据整理
    input:
    A  12 9
    A  -0.3 2.3
    B  1.0 -4
    C  34 1000
    C  -111 900
    C  99 0.09
    
    Output required:
    A 12 9 -0.3 2.3
    B 1.0 -4
    C 34 1000 -111 900 99 0.09
    
    Five codes:
    sort inputfile | awk '{if(a!=$1) {a=$1; printf "\n%s%s",$0,FS} else {a=$1;$1="";printf $0 }} END {printf "\n" }' 
    awk '{a[x++]=$0;b[xx++]=substr($0,1,1)}END{for(i=0;i<x;i++)if(b[i]==b[i+1]){f=f?f a[i+1]:f a[i]a[i+1]}else{if(f=="")f=a[i];gsub(b[i]" ","",f); print b[i] f;f=""}}' unsorted.inputfile
    sort inputfile |awk '$1!=p{if(p)print s; p=$1; s=$0; next}{sub(p,x); s=s $0} END{print s}' 
    awk '{k=$1=$1; sub(k,x); A[k]=A[k] $0} END{for(i in A)print i A[i]}' unsorted.inputfile
    sort inputfile | awk  '{a[$1]=a[$1]?a[$1]" "$2:$2}END{for (i in a) print i,a[i]}'  #仅适合两列的数据类型
    

    2.某列相同时只保留某列最大的那一行

    Output required:
    #第一列相同时,保留第二列最大的一行
    A  12 9
    B  1.0 -4
    C  99 0.09
    sort -k1,1 -k2,2nr inputfile |awk '!a[$1]++{print}'
    

    3.最强多行变一行

    awk 'BEGIN{FS=RS;RS=KS}$1=$1'
    awk '{ORS="\t";$1=$1; print $0}' 
    

    4.求某列数据的标准差,方差,均值,样本数(行数)

    echo "6,3
    > 2,4,5
    > 5,a,6
    > 3,5,4
    > 4,4,5">ppp
    awk -F "," '{print $1}'  ppp|    awk   '{x[NR]=$0; s+=$0; n++} END{a=s/n; for (i in x){ss += (x[i]-a)^2} sd = sqrt(ss/n); print "SS""\t"sd,ss,a,n}' 
    SS      1.41421 10 4 5
    #多列同时求和,此例求一三列
    awk '{FS = OFS = "," }{sum1 += $1; sum2 += $3}END { print sum1, sum2 }'   ppp
    

    5.替换

    sed -e 'y/ATCG/atcg/' seq.fna  #对应替换之修改大小写
    sed -e '/>/!y/ATCG/atcg/' seq.fna  #对应替换之DNA序列反向互补配对,并修改大小写
    sed  '100,2000s/GI/gi/g' seq.fa  #则只替换100行到2000行的内容;
    sed  '100,2000!s/GI/gi/g' seq.fa  #加感叹号取反,在这个范围之外的执行操作;
    sed 's/:.*//g' seq.fna   #删除冒号之后的所有内容;
    sed 's/gi/GI/' seq.fna  #将文件中gi全部替换为大写GI;
    sed 's/\<gi>\/GI/' seq.fna  #精准替换,不会把agiii替换为aGIii;
    sed -i 's/gi/GI/g' seq.fna   #在原文件上进行替换,并且进行全部替换;
    sed -i.bak 's#GI#gi#' seq.fna  #在原文件上进行替换,并进行备份;
    sed -e 's/gi/GI/2;s/ref/REF/2' seq.fna   #只将第二次出现的gi和ref进行替换;
    sed -f sed.list cds.list    #根据文件中的模式进行替换,可同时进行多条件替换;
    sed -n 's/gi/GI/p' seq.fna  #打印发生替换的行;
    awk '{sub(/test/, "no", $0);print}' input.txt #进行替换,类似sed的功能。
    

    6.输出行

    sed -n '1307p'  seq.fna   #输出文件第1307行;
    sed -n '100,200' seq.fna  #输出文件第100到200行;
    sed -n '/ref/p' seq.fna   #输出文件中包含ref关键字的行;
    awk ’{if ($3>=80 && $4>=100) print $0}'  blast_m8.out  #过滤blast比对结果,将identity 大于80,并且比对长度大于100bp的结果输出;
    awk '$0~ /wang/{print $0}' passwd.list   #利用正则表达式,将秘密表中姓wang的账户都输出出来;
    awk 'NR>=20&&NR<=80' input.txt  #输出第20到第80行内容。
    

    7.输出列

    awk -F ":" '{print $1,$NF}' passwd.list   #通过-F修改默认分隔符为冒号,输出第一行与最后一行;
    

    8.去重

    sort -u file;
    sort file|uniq;
    uniq -d file #仅显示重复出现的行列,显示一行。
    uniq -D file #显示所有重复出现的行列,有几行显示几行。
    uniq -u file #仅显示出一次的行列
    uniq -s N file #忽略比较前面的N个字符。
    uniq -w N file #对每行第N个字符以后的内容不作比较。
    awk '!($0 in a) {a[$0];print}' input.txt  # 打印不重复的行,类似uniq的功能;
    awk '!($2 in l){print;l[$2]=1}' input.txt #计算第二列内容非冗余的次数,类似于uniq的功能。
    sort file|uniq -c |awk '{if($1==3) print $0}'  #提取重复三次的项
    

    9.一行变多行

    input:
    A 12 9;-0.3 2.3
    B 1.0 -4
    C 34 1000;-111 900;99 0.09
    
    Output required:
    A  12 9
    A  -0.3 2.3
    B  1.0 -4
    C  34 1000
    C  -111 900
    C  99 0.09
    
    sed -r '/;/s/(\S+)\s+([^;]+);/\1 \2\n\1 /;P;D' input > Output
    

    10.awk浮点数计算要双精度校准才能保证真正准确,尤其是在小数点后9位以后。因为awk的默认精度范围是53bit,也就是双精度的范围内,因此在做高精度数值计算时,一定要注意浮点数的精度要求。

    #不加双精确
    echo 57760731.179959 | awk  '{sum+=$1}END{printf("%.10f\n",sum)}'
    57760731.1799589992
    #加双精度
    echo 57760731.179959 | awk -M -v PREC=100 -v CONVFMT=%.30g '{sum+=$1}END{printf("%.10f\n",sum)}'
    57760731.1799590000
    

    11.保留两位小数

    #awk-仅一列数据
    echo '4.667,9.888
    3.442,3.44203
    3.2214,4.302' > input
    #awk-只第一列
    awk '{printf "%.2f\n",$1}' input
    #awk-两列同时
    awk '{num1=sprintf("%.2f",$1); num2=sprintf("%.2f",$2);print num1,num2}' input
    #awk,常规print,很巧妙的利用int
    awk '{print int($1*100)/100,$2}'
    #bc
    echo "scale=2;3/8" |bc #scale=2将小数位个数设置为2
    0.37
    

    12.两文件取交集

    gawk 'ARGIND==1{a[$1]=$1} ARGIND==2{if(a[$1]!="") print $0}' geneid.txt tpm.txt > gene.tpm.txt
    awk 'NR==FNR{a[$1]=$0}NR>FNR{if($1 in a)print a[$1]"\t"$0}' A B > C
    awk 'NR==FNR{a[$1]=$0;next}{if ($1 in a){print a[$1]"\t"1} else {print $0"\t"0}}' A B  > C
    grep -w -A 1 -Ff genename gene.fasta --no-group-separator > genename.fasta
    
    1. 输出某字符串的前三个字符
    echo 123456|awk '{print substr($1,1,3)}'
    

    14.for循环嵌套时避免重复运算,及自己比自己

    for((i=1;i<=14;i++));  
    do   
    for((j=$i+1;j<=14;j++));  
    do  
    echo ${i}_vs_${j}
    done
    done
    

    15.特殊情况下需要比较两列去重

    echo "1 2
    2 1
    1 1
    2 4">input
    cat input| awk '$1 != $2'
    1 2
    2 1
    2 4
    sort input| awk '!(SEEN[$1,$2]++) && !(($2,$1) in SEEN)' 
    1 2
    2 4
    

    16.大神整理的单行命令集合
    bioinformatics-one-liners
    17.行列转换

    cat file.txt | awk 'BEGIN{c=0;} {for(i=1;i<=NF;i++) {num[c,i] = $i;} c++;} END{ for(i=1;i<=NF;i++){str=""; for(j=0;j<NR;j++){ if(j>0){str = str" "} str= str"\t"num[j,i]}printf("%s\n", str)} }' 
    cat file.txt | awk '{for(i=1;i<=NF;i=i+1){a[NR,i]=$i}}END{for(j=1;j<=NF;j++){str=a[1,j];for(i=2;i<=NR;i++){str=str " " a[i,j]}print str}}'
    cat file.txt | awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]"\t"$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }' 
    

    18.依据第一列做变量,相同时加和

    input:
    A  12
    A  3
    B  1
    C  34
    C  11
    C  99
    
    
    Output required:
    A 15
    B 1
    C 144
    
    awk '{s[$1] += $2}END{ for(i in s){  print i, s[i] } }'  input
    

    19.awk求一列数的均值,最大值,最小值,中位数

    input:
    12
    3
    1
    34
    11
    99
    
    Output required:
    mean:    26.6667
    max:    99
    min:    1
    median:  12
    
     sort -n input | awk '{m[i++]=$1;if(min==""){min=max=$1}; if($1>max) {max=$1}; if($1<min) {min=$1}; total+=$1; count+=1} END {print "mean:\t" total/count,"\nmax:\t"max,"\nmin:\t"min,"\nmedian:\t "m[int(i/2)]}'
    
    #表达矩阵,提取N个样本均值大于0.5的基因
    awk '{a=0;for(i=2;i<=NF;i++){if($i>0.5)a++};if(a>=2)print}' a.tsv
    

    20.跳过前两行,按照第一列数字,从大到小排序

    echo "G C N
    3 b D
    1 2 9
    5 2 3
    2 3 4" > input
    Output required:
    G C N
    3 b D
    5 2 3
    2 3 4
    1 2 9
    (awk 'NR<3' input && awk 'NR>2' input| sort -k1,1nr) > output
    

    其实这个命题引出了shell里括号的用法,这里的小括号将命令做成了命令组,括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。 更多相关知识可见:shell中各种括号的作用

    21.for循环1到10

    for i in `echo 1 2 3 4 5 6 7 8 9 10`;do echo "${i}";done
    for i in `seq 10`;do echo "${i}";done #10可为参数传递
    for i in $(seq 1 1 10);do echo "${i}";done #10可为参数传递
    for i in {1..10..1};do echo "${i}";done
    for i in {1..10};do echo "${i}";done
    
    

    reference:
    https://www.unix.com/shell-programming-and-scripting/188147-how-merge-multiple-rows-into-single-row-if-first-column-matches.html
    https://mp.weixin.qq.com/s/FTi2PwMlDdmWsn2Db71uSA

    相关文章

      网友评论

        本文标题:2020-07-03 常用有趣命令之数据处理

        本文链接:https://www.haomeiwen.com/subject/uxleqktx.html