Analisando o arquivo de acordo com o par de IDs e valores menores mais altos

1

O arquivo1 tem 8 colunas. As colunas 3 e 4 fazem um pareamento como rs | 860 rs | 756 e os valores associados ao par estão na coluna 8.

bb  yy  rs|860  rs|756  xx  aa  0.7 2234
bb  yy  rs|310  rs|260  xx  aa  0.3 9838
bb  yy  rs|110  rs|77   xx  aa  0.5 2291
bb  yy  rs|756  rs|860  xx  aa  0.4 2269
bb  yy  rs|110  rs|77   xx  aa  0.9 1112
bb  yy  rs|756  rs|860  xx  aa  0.8 3269
bb  yy  rs|233  rs|79   xx  aa  0.4 1397
bb  yy  rs|79   rs|233  xx  aa  0.7 1397

O par de column3 e 4 ou 4 e 3 deve ser tratado da mesma forma, por exemplo, rs | 860 rs | 756 == rs | 756 rs | 860. Em seguida, pode haver repetição nos pares na linha um também está presente na linha 4 e na linha 6 (inversamente). Simplesmente aqui AB = BA = BA. Primeiro eu quero ordenar o col3 e col4 rowwise, que pode fazer dados como AB = AB = AB. Em seguida, em toda a ocorrência dos pares, deve-se manter apenas um valor máximo na coluna8. Por exemplo, rs | 860 rs | 756 tem valor máximo na linha 6 (ou seja, 3269), portanto a linha 1 e a linha 4 devem ser excluídas. Da mesma forma, no caso de rs | 110 rs | 77 row5 deve ser excluído. Em seguida, no caso de pares com valor semelhante na coluna 8, um com maior valor na coluna 7 deve ser retido. Por exemplo, no caso de rs | 233 rs | 79 row7 com valor mais baixo na coluna7 (0.4) deve ser excluído. Para qualquer par, se a coluna8 e a coluna7 não tiverem uma diferença maior / menor, qualquer uma pode ser excluída.

A saída desejada File2

bb  yy  rs|260  rs|310  xx  aa  0.3 9838
bb  yy  rs|77   rs|110  xx  aa  0.5 2291
bb  yy  rs|756  rs|860  xx  aa  0.8 3269
bb  yy  rs|79   rs|233  xx  aa  0.7 1397
    
por Patel 25.07.2017 / 01:11

2 respostas

2

Aqui está uma solução awk não elegante:

{
    split($3, a, "|")
    split($4, b, "|")
    if (a[2] > b[2]){
        $3=b[1]"|"b[2]
        $4=a[1]"|"a[2]
    }
    split(arr[$3" "$4], c, " ")
    if ($8 > c[8]){
        arr[$3" "$4] = $0
    }
}
END{
    for (item in arr){
        print(arr[item])
    }
}

Executar com

awk -f script.awk input

Não retém o espaçamento e a ordenação é aleatória.

    
por 25.07.2017 / 02:29
0

Aproveitando a resposta do pfnuesel ,

{
    split($3, a, "|")
    split($4, b, "|")
    if (a[2] > b[2]){
        $3=b[1]"|"b[2]
        $4=a[1]"|"a[2]
    }
    key=$3" "$4
    split(arr[key], c, " ")
    if ($8 > c[8]  ||  ($8 == c[8] && $7 > c[7])){
        arr[key] = $0
    }
}
END{
    for (item in arr){
        print(arr[item])
    }
}

Isso pressupõe, como mostrado (mas não explicitamente declarado) na pergunta, que os valores nas terceira e quarta colunas são da forma

some_string | number

onde os espaços são apenas para ilustração, e a string não contém nenhum caractere | . Esses tokens devem ser classificados com base nos valores do número s; os prefixos string não são comparados.

Como na resposta do pfnuesel , o uso é

awk -f script.awk file1

O espaçamento exato do arquivo de entrada é perdido, mas um espaçamento de coluna legível pode ser (re) criado por meio de canalização em column -t ; por exemplo,

awk -f script.awk file1 | column -t > file2
    
por 01.08.2017 / 06:29