【问题标题】:Match closest value from two different files and print specific columns匹配两个不同文件中最接近的值并打印特定列
【发布时间】:2015-04-28 00:14:15
【问题描述】:

大家好,我有两个文件,每个文件都有 N 列和 M 行。

文件1

1 2 4 6 8
20 4 8 10 12
15 5 7 9 11

文件2

1 a1 b1 c5 d1
2 a1 b2 c4 d2
3 a2 b3 c3 d3
19 a3 b4 c2 d4
14 a4 b5 c1 d5

我需要的是在第 1 列中搜索最接近的值,并在输出中打印特定列。所以例如输出应该是:

文件3

1 2 4 6 8
1 a1 b1 c5 d1
20 4 8 10 12
19 a3 b4 c2 d4
15 5 7 9 11
14 a4 b5 c1 d5

由于 1 = 1,19 最接近 20,14 最接近 15,因此输出是那些行。 如何在 awk 或任何其他工具中做到这一点?

救命!

这是我到现在为止的:

echo "ARGIND == 1 {
s1[\$1]=\$1;
s2[\$1]=\$2;
s3[\$1]=\$3;
s4[\$1]=\$4;
s5[\$1]=\$5;
}
ARGIND == 2 {
bestdiff=-1;
for (v in s1)
if (bestdiff < 0 || (v-\$1)**2 <= bestdiff) 
{
s11=s1[v];
s12=s2[v];
s13=s3[v];
s14=s4[v];
s15=s5[v];
bestdiff=(v-\$1)**2;
if (bestdiff < 2){
print \$0
print s11,s12,s13,s14,s15}}">diff.awk
awk -f diff.awk file2 file1

输出:

1 2 4 6 8
1 a1 b1 c5 d1
20 4 8 10 12
19 a3 b4 c2 d4
15 5 7 9 1
14 a4 b5 c1 d5
1 2
1 1
14 15

我不知道为什么最后三行。

【问题讨论】:

  • 当然需要输入这两个文件。由于您使用 awk 进行标记,您可能已经开始编写代码。请分享吧!
  • 是的,我错误地表达了自己。但我仍然没有什么可分享的。有什么想法吗?
  • 两个文件的行数一样吗? “最接近”是什么意思?如果我们在第一个文件中只有一行的值为“30”,而第二个文件中的值为“40”,是否足够接近?
  • @AndreySabitov 行数不一样,是的,如果没有另一个足够接近的话,30 是最接近 40 的。

标签: bash awk


【解决方案1】:

最后我试图给出一个答案:

function closest(b,i) { # define a function
  distance=999999; # this should be higher than the max index to avoid returning null
  for (x in b) { # loop over the array to get its keys
    (x+0 > i+0) ? tmp = x - i : tmp = i - x # +0 to compare integers, ternary operator to reduce code, compute the diff between the key and the target
    if (tmp < distance) { # if the distance if less than preceding, update
      distance = tmp
      found = x # and save the key actually found closest
    }
  }
  return found  # return the closest key
}

{ # parse the files for each line (no condition)
   if (NR>FNR) { # If we changed file (File Number Record is less than Number Record) change array
     b[$1]=$0 # make an array with $1 as key
   } else {
     akeys[max++] = $1 # store the array keys to ensure order at end as for (x in array) does not guarantee the order
     a[$1]=$0 # make an array with $1 as key
   }
}

END { # Now we ended parsing the two files, print the result
  for (i in akeys) { # loop over the first file keys
    print a[akeys[i]] # print the value for this file
    if (akeys[i] in b) { # if the same key exist in second file
      print b[akeys[i]] # then print it
    } else {
      bindex = closest(b,akeys[i]) # call the function to find the closest key from second file
      print b[bindex] # print what we found
    }
  }
}

我希望评论足够清楚,如果需要,请随时发表评论。

警告如果您在第二个文件中有大量行,这可能会变得非常慢,因为第二个数组将针对第一个文件的每个键进行解析,而第二个文件中不存在。/警告

给定您的样本输入 a1 和 a2:

$ mawk -f closest.awk a1 a2
1 2 4 6 8
1 a1 b1 c5 d1
20 4 8 10 12
19 a3 b4 c2 d4
15 5 7 9 11
14 a4 b5 c1 d5

【讨论】:

  • 非常感谢,完美运行!但是对我来说稍微修改它有点太先进了。如果我需要为第二列找到最接近的值,我该怎么做。这意味着例程在第一列中找到最接近的之后,现在也搜索最接近的比较第二列吗?。
  • 我不明白这一点,你会如何比较数值和文本值?据说我的代码中有一个错误,我打印了两次bindex(第二个文件的第一个字段)(一次作为索引,一次作为行的一部分)。我将进行编辑以解决此问题。
  • 你是对的。是的,事情是我当然只会比较数字。我只是在寻找一种通用的方法,但它比我想象的要复杂。只是想象所有的列都是数字。
  • 这将涉及创建另一个具有第二个字段 ($2) 的数组并将其传递给函数......但是如果没有用例,我不确定是否理解目标。也许您可以在试用版中写一个新问题以及失败的地方?
  • 如果需要,您可以参考这个问题来为您的第一步提供背景信息。
猜你喜欢
  • 1970-01-01
  • 2020-05-18
  • 2018-08-08
  • 2016-10-23
  • 2018-07-12
  • 2022-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多