我有三个数据框:
数据框1
chr start end Id chr1 1 400 SN_1 chr1 401 800 SN_2 chr1 801 1200 SN_3 chr1 1201 1600 SN_4 chr1 1601 2000 SN_5 chr1 2001 2400 SN_6 chr1 2401 2800 SN_7
数据框2
chr start end Id chr1 401 800 SN_2 chr1 801 1200 SN_3 chr1 1201 1600 SN_4
数据框3
chr start end Id chr1 1201 1600 SN_4 chr1 1601 2000 SN_5 chr1 2001 2400 SN_6
我想获得一个最终数据帧,其中根据第一个数据帧的第四列,将报告与第二个和第三个数据帧的第四列相关的匹配或不匹配。在新的数据帧中,如果存在匹配,则将报告相同的 Id,但如果存在匹配,则 Id 名称将替换为 NA。也许只写输入和输出会更容易理解。像这样的东西:
期望的输出:
chr start end Id Id Id chr1 1 400 SN_1 NA NA chr1 401 800 SN_2 SN_2 NA chr1 801 1200 SN_3 SN_3 NA chr1 1201 1600 SN_4 SN_4 SN_4 chr1 1601 2000 SN_5 NA SN_5 chr1 2001 2400 SN_6 NA SN_6 chr1 2401 2800 SN_7 NA NA
我尝试过使用 unix 命令中的 join 但无法比较不同大小的数据帧。任何想法都会非常感激。
答案1
awk解决方案:
awk 'FILENAME == ARGV[1] && NR>1{ df2[$2,$3,$4] }
FILENAME == ARGV[2] && FNR>1{ df3[$2,$3,$4] }
FILENAME == ARGV[3]{ if(FNR == 1) { printf("%s\t%s\t%s\n",$0,$NF,$NF) }
else { printf("%s\t%s\t%s\n",$0, (($2,$3,$4) in df2)? $NF :"NA",(($2,$3,$4) in df3)? $NF :"NA")}
}' df2 df3 df1 | column -t
输出:
chr start end Id Id Id
chr1 1 400 SN_1 NA NA
chr1 401 800 SN_2 SN_2 NA
chr1 801 1200 SN_3 SN_3 NA
chr1 1201 1600 SN_4 SN_4 SN_4
chr1 1601 2000 SN_5 NA SN_5
chr1 2001 2400 SN_6 NA SN_6
chr1 2401 2800 SN_7 NA NA
df2
,df3
是df1
你的第二个、第三个和第一个数据框分别文件FILENAME
- 内置变量指向当前处理的文件的名称ARGV
- 指向传递给 awk 脚本的所有参数的内置变量。即ARGV[1]
包含df2
FILENAME == ARGV[1] && NR>1
- 遇到第一个文件(即df2
从第二行开始)df2[$2,$3,$4]
- 从“获取关键价值”数据框2" 作为数组的键df2
FILENAME == ARGV[2] && FNR>1
df3
- 遇到从第二行开始的第二个文件(即)df3[$2,$3,$4]
- 从“获取关键价值”数据框3" 作为数组的键df3
FILENAME == ARGV[3]
- 遇到第三个文件(即df1
),主要数据框
答案2
perl -lane '$,="\t";
!@ARGV and $. == 1 and print($_, qw/Id/x2),next;
$h{$F[1],$F[2]}->[@ARGV] = $F[3];
!@ARGV and print $_, map { $h{$F[1],$F[2]}->[$_] // q/NA/ } 1..2;
$. = 0 if eof;
' file3 file2 file1
结果
chr start end Id Id Id
chr1 1 400 SN_1 NA NA
chr1 401 800 SN_2 SN_2 NA
chr1 801 1200 SN_3 SN_3 NA
chr1 1201 1600 SN_4 SN_4 SN_4
chr1 1601 2000 SN_5 NA SN_5
chr1 2001 2400 SN_6 NA SN_6
chr1 2401 2800 SN_7 NA NA
工作原理
- 输入的顺序为:dataframe3、dataframe2 和 dataframe1。
- 假设 dataframe1 已填充所有第四列,IOW,没有丢失。
- 我们
Perl
以行读入+自动分割模式调用:perl -lane
- 在读取第3帧期间,@ARGV有2个元素,在第2帧期间读取1个元素,在第3帧期间读取0个元素。
- 我们填充一个散列 ,
%h
其键是第 2+3 个字段,$F[1],$F[2]
值是匿名数组引用,因此称为:$h{...}[...]
。 - 在第一个数据帧(@ARGV有0个元素)期间,我们用第一个数据帧的内容打印每一行,并确定对应当前第二个数据帧的第二/第三帧的数组元素是否存在/第三个字段。