我有一个看起来像这样的大数据集:
5 6 5 6 3 5
2 5 3 7 1 6
4 8 1 8 6 9
1 5 2 9 4 5
对于每一行,我想从第二个字段中减去第一个字段,第四个字段,依此类推,依此类推(始终均匀)。然后,我想报告所有对所有对差异都超过一定限制的行(例如2)。我还应该能够报告下一个最佳行,即一个成对比较无法满足限制的行,但所有其他对符合极限。
从上面的示例中,如果我将限制设置为2,则我的输出文件应包含最佳行:
2 5 3 7 1 6 # because (5-2), (7-3), (6-1) are all > 2
4 8 1 8 6 9 # because (8-4), (8-1), (9-6) are all > 2
下一个最佳行(S)
1 5 2 9 4 5 # because except (5-4), both (5-1) and (9-2) are > 2
我当前的方法是读取每一行,将每个字段保存为一个变量,进行减法。但是我不知道该如何进一步进行。
谢谢,
在文件"最佳"中打印"最佳"行,并打印"下一个最佳"行的" sextbest"
awk '
{
fail_count=0
for (i=1; i<NF; i+=2){
if ( ($(i+1) - $i) <= threshold )
fail_count++
}
if (fail_count == 0)
print $0 > "best"
else if (fail_count == 1)
print $0 > "nextbest"
}
' threshold=2 inputfile
非常简单的东西。
- 一次循环通过字段2。
- 如果(下一个字段 - 当前字段)不超过
threshold
,则增量fail_count
如果该行的
fail_count
为零,则意味着它属于"最佳"行。否则,如果该行的
fail_count
是一个,则属于"下一个最佳"行。
这是一个行动:
#!/bin/bash
threshold=$1
shift
file="$@"
a=($(cat "$file"))
b=$(( ${#a[@]}/$(cat "$file" | wc -l) ))
for ((r=0; r<${#a[@]}/b; r++)); do
br=$((b*r))
for ((c=0; c<b; c+=2)); do
if [[ $(( ${a[br + c+1]} - ${a[br + c]} )) < $threshold ]]; then
break; fi
if [[ $((c+2)) == $b ]]; then
echo ${a[@]:$br:$b}; fi
done
done
用法:
$ ./script.sh 2 yourFile.txt
2 5 3 7 1 6
4 8 1 8 6 9
然后可以轻松地重定向此输出:
$ ./script.sh 2 yourFile.txt > output.txt
注意:如果每行之间有那些空的行,这将无法正常工作...但是我敢肯定,以上会让您走得很好。
我可能不会在bash中这样做。就我个人而言,我会在Python中做,这通常对那些小型和杂音的脚本有好处。
如果您将数据放在文本文件中,则可以在此处阅读有关如何将这些数据作为行列表中的python中的读取。然后,您可以使用循环处理每行:
threshold = 2
results = []
for line in content:
numbers = [int(n) for n in line.split()] # Split it into a list of numbers
pairs = zip(numbers[::2],numbers[1::2]) # Pair up the numbers two and two.
result = [abs(y - x) for (x,y) in pairs] # Subtract the first number in each pair from the second.
if sum(result) > threshold:
results.append(numbers)
又是另一个bash版本:
首先返回结果代码的check function
:
function getLimit() {
local pairs=0 count=0 limit=$1 wantdiff=$2
shift 2
while [ "$1" ] ;do
[ $(( $2-$1 )) -ge $limit ] && : $((count++))
: $((pairs++))
shift 2
done
test $((pairs-count)) -eq $wantdiff
}
比现在:
while read line ;do getLimit 2 0 $line && echo $line;done <file
2 5 3 7 1 6
4 8 1 8 6 9
和
while read line ;do getLimit 2 1 $line && echo $line;done <file
1 5 2 9 4 5
如果您可以使用awk
$ cat del1
5 6 5 6 3 5
2 5 3 7 1 6
4 8 1 8 6 9
1 5 2 9 4 5
1 5 2 9 4 5 3 9
$ cat del1 | awk '{
> printf "%s _ ",$0;
> for(i=1; i<=NF; i+=2){
> printf "%d ",($(i+1)-$i)};
> print NF
> }' | awk '{
> upper=0;
> for(i=1; i<=($NF/2); i++){
> if($(NF-i)>threshold) upper++
> };
> printf "%d _ %sn", upper, $0}' threshold=2 | sort -nr
3 _ 4 8 1 8 6 9 _ 4 7 3 6
3 _ 2 5 3 7 1 6 _ 3 4 5 6
3 _ 1 5 2 9 4 5 3 9 _ 4 7 1 6 8
2 _ 1 5 2 9 4 5 _ 4 7 1 6
0 _ 5 6 5 6 3 5 _ 1 1 2 6
您可以根据需要进一步处理结果。结果通过"善良"顺序排序。