Code
之前一直用vlookup
做垂直查找,直到后来接触了测序数据...动辄一个excel几十兆,丐版的MBPvlookup
经常就卡死了;后来用R的left_join,但还是感觉不方便,先要读进去,还要保证colname一致...最后忍不了了,直接一顿寻找,找到了用awk直接对俩文件进行vlookup。
代码如下:
shawnwx@bogon tep$ awk 'NR==FNR{a[$1]=$0;next}NR>FNR{if($1 in a)print $0"\t"a[$1]}' file_query file_source >output.xls
可以写成awk script然后alias重命名,当然也可以添加到环境变量。
# 新建一个awk script
vim vlookup.awk
# 按I进入编辑模式,把下面代码粘贴进去。然后按ESC,按: wq.
NR==FNR{a[$1]=$0;next}NR>FNR{if($1 in a)print $0"\t"a[$1]}
# 重命名成一个简短的vlkup
alias vlkup="awk -f vlookup.awk"
# 现在就可以直接使用vlkup
vlkup file_query file_source > output.xls
# 写入环境变量(mac),一般会把常用的脚本放到一个专门的路径下,比如我的在~/aliascode
open ~/.bash_profile
# 将下面代码写入保存
alias vlkup="awk -f ~/aliascode/vlookup.awk"
source ~/.bash_profile
# =====================done======================
解读
在awk里,NR和FNR的含义相近,唯一的区别就是作用范围,NR是所有读取的行信息计数,而FNR是正在读取文件的行信息技术,FNR在文件切换时会从0重新开始计数,所以上述语句的意思是:
NR==FNR在判断是不是在读a.txt,如果是a.txt则以第一个数据项为key,以整行信息为数据组成数组;
NR>FNR则判断是不是在读b.txt,因为此时NR=(a.txt的总行数+FNR),如果是,则判断第一个数据项在不在a.txt数据组成的数组里,如果在,则打印本行加数组项。
例子:
o@t /tmp $ cat a.txt
1 abc
2 def
3 ghi
4 jlm
o@t /tmp $ cat b.txt
3 shit
1 rubb
o@t /tmp $ awk 'NR==FNR{a[$1]=$0;next}NR>FNR{if($1 in a)print $0"\n"a[$1]}' a.txt b.txt
3 shit
Reference:
补充
当时用这个时候最后还返回了A的?第一列,其实没有这个必要,最后改了一下
NR==FNR{a[$1]=$0;next}NR>FNR{if($1 in a)print $0}
直接print出找到的。因为有一次出来居然换行了,我这里是Tab分割的,也木有用换行符呀。看来还是要深入学习一下
March 7, 2019补充
今天要合数据,想着批量做vlk,但发现之前写的这个并不合适,因为之前只返回找到的值,对没有匹配的值实际上想返回NA所以重新写了如下:
NR==FNR{a[$1]=$0;next}NR>FNR{if($1 in a)print a[$0]; else print $1"\t""NA""\t""NA""\t""NA"}
# 前面如何判断就不说了,就说后面返回,$1在a里面,则打印a这一样,如果不在则返回$1\tNA\tNA\tNA 使用方法还是和之前一样
# awk -f vlkupV1.awk data.file ID.file >output.file,然后又做了个叫vlk的快捷命令
alias vlk="awk -f ~/aliascode/vlkupV1.awk"
vim ~/.bashrc
# vlookup for return in "NA" for "else" condition
alias vlk="awk -f ~/aliascode/vlkupV1.awk"
:wq
后面应该还会有补充....不断完善汇中慢慢学习..