Bash是一种基于索引列表比较两个不同文件中特定列的方法
我有两个选项卡分隔的文件,共1708行,列数不同。我的目标是比较所有行存储的值,但只比较一些特定列的值。我有两个列表,其中包含要比较的列的编号;这里有一个例子:Bash是一种基于索引列表比较两个不同文件中特定列的方法,bash,awk,Bash,Awk,我有两个选项卡分隔的文件,共1708行,列数不同。我的目标是比较所有行存储的值,但只比较一些特定列的值。我有两个列表,其中包含要比较的列的编号;这里有一个例子: 菲拉➝ col_ind_A=[12,20,24,55] 文件➝ col_ind_B=[14,28,35,79] 这里,应将文件A的第12列与文件B的第14列、文件A的第20列与文件B的第28列进行比较,依此类推。如果文件A的值为0,而文件B的值为0,我想在该位置修改文件C(文件A的副本),然后存储文件B的值(不是0): 我已经看到比
- 菲拉➝ col_ind_A=[12,20,24,55]
- 文件➝ col_ind_B=[14,28,35,79]
for(i在1:1708中){#行
对于(j in 1:31946){#cols
如果(fileA[i,col_ind_A[j]='0'&&fileA[i,col_ind_A[j]!=fileB[i,col_ind_B[j]]){
fileC[i,col_ind_A[j]一个执行此操作的perl脚本:
!/usr/bin/env perl
严格使用;
使用警告;
使用自动模具;
使用功能qw/say/;
使用列表::Util qw/pairs/;
#根据需要进行调整。
我的@columns=(12=>14,20=>28,24=>35,55=>79);
我的($filea_name,$fileb_name)=@ARGV;
@columns=成对映射{$\ 1}@columns;
打开我的$filea,“首先逐行加入文件,然后检查要检查的条件
# recreate input
cat >file1 <<EOF
col11 col12 col13
A C G
G 0 T
EOF
cat >file2 <<EOF
col13 col14 col15
A C G
G T T
EOF
paste file1 file2 |
awk '{ if ($2 == 0 && $2 != $6) $2=$6; print $1, $2 ,$3}'
我猜从for(1:1708中的I){#rows
中,假设两个文件中的列数相同,您可能希望迭代所有列:
paste file1 file2 |
awk '{
for (i=1;i<=NF/2;++i) if ($i == 0 && $i != $(i*2)) $i = $(i*2);
for (i=1;i<=NF/2;++i) printf "%s%s", $i, i==NF/2?ORS:OFS;
}'
粘贴文件1文件2|
awk'{
对于(i=1;i由于您要求提供awk
解决方案,这里有一个简单的解决方案:
awk -v col_ind_A='12 20 24 55' -v col_ind_B='14 28 35 79' '
BEGIN { OFS="\t"
split(col_ind_A, ciA)
split(col_ind_B, ciB)
while (getline <"FileB" > 0 && split($0, B) && getline <"FileA" > 0)
{
for (i in ciA) if ($ciA[i] == 0) $ciA[i] = B[ciB[i]]
print >"FileC"
}
}'
您可以共享输入文件的示例记录吗?我会将文件转换为SQLite或其他db。为相关列编制索引以提高速度,并要求db引擎处理查询。最终将最终输出的格式重新设置为与数据文件类似的格式。@Armali您说得对,我刚刚解决了这个问题,谢谢。至于我的记录示例,它们是您创建的.ped文件sing PLINK,它们看起来与示例中完全相同,但有更多的行和列。我希望这会有所帮助。关于假设两个文件中的列数相同的问题,询问者写道:我有两个标签分隔的文件,共1708行,列数不同。我认为合并文件可能不是最好的主意,因为fileA有180000多列umns和fileB有30000多个,但无论如何,感谢awk位非常有用:)这看起来真的很好,是否可以将列也添加为包含“'12=>14,20=>28,24=>35,55=>79,”,因为通信数量超过30000。谢谢!getline 0
应该是(getline 0
。FileA也一样。R代码工作得非常完美,速度非常快。非常感谢!!
col11 col12 col13
A C G
G T T
paste file1 file2 |
awk '{
for (i=1;i<=NF/2;++i) if ($i == 0 && $i != $(i*2)) $i = $(i*2);
for (i=1;i<=NF/2;++i) printf "%s%s", $i, i==NF/2?ORS:OFS;
}'
awk -v col_ind_A='12 20 24 55' -v col_ind_B='14 28 35 79' '
BEGIN { OFS="\t"
split(col_ind_A, ciA)
split(col_ind_B, ciB)
while (getline <"FileB" > 0 && split($0, B) && getline <"FileA" > 0)
{
for (i in ciA) if ($ciA[i] == 0) $ciA[i] = B[ciB[i]]
print >"FileC"
}
}'
for (i in 1:nrow(FileA))
{
j = which(FileA[i, col_ind_A] == 0)
FileC[i, col_ind_A[j]] = FileB[i, col_ind_B[j]]
}