bash - 如何在矩阵中查找行的最大值的索引

时间:2017-07-05 19:16:45

标签: bash matrix indexing max row

以下是我的意见:

chr1 58962 -0.042053 -22.525086 -20.817409 -19.525688 
chr1 58989 -0.014479 -14.459352 -12.824315 -11.744024
chr1 59155 -0.062963 -13.810858 -12.749009 -12.102778
chr1 59256 -0.014105 -7.371202  -9.117587  -11.525907

我在bash中寻找一种方法来获取每行的最大值的索引。我不想考虑前两列。

我可以在R:

中非常简单地完成
data=fread(myfile)
maxindex=apply(data[,3:6],1,which.max)

这样输出就是一个包含索引的数组。这是我想要的那种输出。在这种情况下:

maxindex= 1  1  1  1

不幸的是整个文件是32 Gb(包含300000行和8183列的大表),因此即使在我补贴原始文件之后R也无法接受它。我已经读到bash不能按行工作,但还有办法做我想做的事吗?

3 个答案:

答案 0 :(得分:2)

使用以下 awk 解决方案,它将 更快 而不是 perl < / em> 方法(在&#34;大&#34;文件):

awk '{ m=$3; p=1; for(i=4;i<=NF;i++) { 
           if ($i>m) { m=$i; p=i-2 } } printf "%d ",p }' file > max_indices
  • m=$3 - 初始最大值(第3个字段值)

  • for(i=4;i<=NF;i++) - 迭代剩余字段

  • if ($i>m) { m=$i; p=i-2 } - 捕获最大值

答案 1 :(得分:0)

Perl解决方案:

perl -ane '$r = 2;
           for my $i (3 .. $#F) {
               $r = $i if $F[$i] > $F[$r];
           }
           print $r - 1, " ";
          ' < input-file > output-file
  • -n逐行处理输入行
  • -a将空格上的每一行拆分为@F数组
  • $r存储最大值的索引(在处理每一行之前设置为2)
  • 在for循环中,我们尝试所有其他索引并存储最大索引(如果找到它)
  • 处理完整行后,我们输出索引 - 1(因为索引从Perl中的0开始,你想忽略前两行)

答案 2 :(得分:0)

如果你想用基本的bash操作编写脚本,你可以这样做:

#!/bin/bash

# Function to find the max-value of a one-dimensional array
findMax() 
{   
    [[ -z $2 ]] && return # Exit early if the string is empty

    declare -a pararr=($@) #Insert the input into an array we can work with

    # Basic brute-force algorithm to find the highest value in the array 
    maxInd=2 
    for (( i = 3; i < $#; i++ )); do
        (( $(echo "${pararr[$i]} > ${pararr[$maxInd]}" | bc) )) && maxInd=$i
    done

    echo -n " $(( maxInd - 2 ))"
}

echo -n "Maxindex:"

# Feed our findMax row-by-row from the input file
while read -r line; do
    findMax $line
done < ${!#}


echo # Append newline at the end

此脚本采用格式化为您的示例的文件,并逐行搜索最大索引。但是,在文件中,每行必须与换行符分隔,如你的示例所示,否则可能会发生一些不稳定的事情。如果您愿意,您当然可以扩展脚本以处理其他格式。

但是,如果您想对非常大的文件执行此操作,我认为其他人提供的解决方案将更适合。我不太了解bash的开销,因为我在大多数性能关键的应用程序中都使用C / C ++,但我猜它并不是很有效。

(( $(echo "${pararr[$i]} > ${pararr[$maxInd]}" | bc) )) && maxInd=$i

这部分脚本真的很难看,但我不知道有什么更好的方法来做浮点运算。我们在这里做的是我们正在评估我们目前在行中的当前位置,我们目前发现的价值最大。所以这个:

echo "${pararr[$i]} > ${pararr[$maxInd]}

可能会扩展到类似的东西

0.356 > 1.567

然后我们将它传递给bc,它为我们进行浮点比较。如果我们当前的位置大于我们到目前为止找到的最大值,我们将maxIndex设置为该值。希望这会有所帮助。