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

  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

13.两文件取差集、并集、交集

echo "a
b
c
d" > a

echo "b
c
d
e
f"> b

#交集
sort a b | uniq -d
b
c
d

#并集
sort a b| uniq 
a
b
c
d
e
f

#差集
#a特有
sort a b b | uniq -u
a

#b特有
sort b a a | uniq -u
e
f
  1. 输出某字符串的前三个字符
echo 123456|awk '{print substr($1,1,3)}'

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

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

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

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

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

#输出的分隔符有点乱
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 "\t" 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]; } }' 

19.依据第一列做变量,相同时加和或者求均值

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

求均值

Output required:
A 7.5
B 1
C 48

awk '{sum[$1]+=$2; count[$1]++} END {for (key in sum) {if (count[key]>1) {avg=sum[key]/count[key]; print key, avg} else {print key, sum[key]}}}' input.txt

20.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

#计算变异系数
awk '{ sum += $1; sumsq += ($1)^2; n++ } END { mean = sum / n; sd = sqrt((sumsq - sum^2/n) / (n - 1)); cv = sd / mean * 100; print cv }' data.txt | bc

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

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中各种括号的作用

22.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

23.几种bed文件的sort策略

sortBed -i  input.bed
bedtools sort -i input.bed
sort -k 1,1 -k2,2n input.bed
sort -V -k 1,3 input.bed 
sort -V  -k 1,1 -k2,2n input.bed #通常这个最好用
-V参数重要, --version-sort          natural sort of (version) numbers within text

24.python模块安装

python2 -m pip install biopython --user
#  in a virtual environment or using Python 2
pip install biopython

#  for python 3 (could also be pip3.10 depending on your version)
pip3 install biopython

#  if you get permissions error
sudo pip3 install biopython
pip install biopython --user

#  if you don't have pip in your PATH environment variable
python -m pip install biopython  --user

#  for python 3 (could also be pip3.10 depending on your version)
python3 -m pip install biopython  --user

#  using py alias (Windows)
py -m pip install biopython

#  for Anaconda
conda install -c conda-forge biopython

#  for Jupyter Notebook
!pip install biopython

25.perl 模块安装

#非root用户。推荐运行下面的代码获取自己的私人cpan下载器。
wget -O- http://cpanmin.us | perl - -l ~/perl5 App::cpanminus local::lib
eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`
echo 'eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`' >> ~/.bashrc
echo 'export MANPATH=$HOME/perl5/man:$MANPATH' >> ~/.bashrc
#完成以上操作后以后只需要运行以下命令即可
cpanm Convert::Color

# 不区分大小写、加上了perl前缀、中间以短横线连接
conda install -c bioconda perl-convert-color

26.输出当下系统时间

echo $(date +%Y-%m-%d" "%H:%M:%S)

27.整行均值过滤(跳过第一列)

cutvalue=`echo 1`
awk -vcut="${cutvalue}" '{a=0;for(i=2;i<=NF;i++){if($i>cut)a++};if(a>=2)print}' matrix.tsv

28.分组求均值
示例里是5个分组(sample)*5次重复的数据示例
修改的话,可按:6个时间点,每个时间点3个重复,改为-v sample=6 -v repeat=3即可。

awk -v sample=5 -v repeat=5 '{for(i=1;i<=sample;i++){I=(i-1)*repeat;sum=0;for(j=1;j<=repeat;j++){sum+=$(I+j+1)};if(allsum[$1]=="")allsum[$1]=$1"\t"sum/repeat; else allsum[$1]=allsum[$1]"\t"sum/repeat}}END{for(k in allsum)print allsum[k]}' a.tpm.tsv 
gene1  0         0.007919  0.0417744  436.062   833.515
gene2  83.9412   21.8847   45.4605    86.878    70.9082
gene3  11.1208   2.56975   7.76237    12.7182   11.5676

29.shell下按列名处理文件
使用bioawk软件

$ cat b.txt
geneid  T1_1    T1_2    T1_3    T2_1    T2_2    T2_3
gene1   1       3       9       2       8       5
gene2   3       4       5       8       0       8
$ bioawk -t -c header '{print $geneid,$T1_1,$T2_1}' b.txt
geneid  T1_1    T2_1
gene1   1       2
gene2   3       8

使用awk,但是很绕

$ awk 'BEGIN{OFS="\t"}NR==1{for(i=1;i<=NF;i++){a[$i]=i}}NR>=1{print $a["geneid"],$a["T1_1"],$a["T2_1"]}' b.txt
geneid  T1_1    T2_1
gene1   1       2
gene2   3       8

30.awk来做长数据和宽数据之间的转换

echo "a|A|10
a|B|0
b|C|10" |sed 's/|/\t/g' > test.long

cat test.long | awk -F'\t' '{data[$2][$1]=$3; samples[$1]} END {header="id"; for(sample in samples){header=header"\t"sample} print header; for(gene in data){output=gene; for(sample in samples){output=output"\t"(data[gene][sample]?data[gene][sample]:"0")} print output}}' > test.long2wide

cat test.long2wide | awk -F'\t' 'NR==1{for(i=1; i<=NF;i++){headers[i] = $i}}NR>1{for(i = 2; i <= NF; i++) {print $1 "\t" headers[i] "\t" $i}}'  > test.wide2long

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
//www.greatytc.com/u/e86db5f5bbb8

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容