Como extrair grupos de uma coluna com base na combinação única de duas outras colunas

Como extrair grupos de uma coluna com base na combinação única de duas outras colunas

Eu tenho dados como este:

Sample_1    Apples  Red
Sample_2    Apples  Red
Sample_3    Apples  Red
Sample_4    Apples  Red
Sample_5    Apples  Red
Sample_6    Apples  Green
Sample_7    Apples  Green
Sample_8    Apples  Green
Sample_9    Apples  Green
Sample_10   Apples  Green
Sample_11   Apples  Yellow
Sample_12   Apples  Yellow
Sample_13   Apples  Yellow
Sample_14   Apples  Yellow
Sample_15   Apples  Yellow

Como posso extrair iterativamente as amostras da primeira coluna com base na combinação dos grupos formados nas outras duas colunas, para obter as amostras 1-5, 6-10 e 11-15?

O que eu quero fazer é extrair as listas de amostras (como os grupos acima) como entrada para outro comando, por exemplo:

comm -23 <(sort <all_samples.txt>) <(sort <[input from above]>) > <difference.txt>

Eu tentei:

awk '{print $2"\t"$3}' <file.txt> | uniq

Para obter as combinações únicas da segunda e terceira colunas, mas parece que não consigo fazer nada com isso, principalmente puxar a primeira coluna, que é o que preciso.

Responder1

É isso que você está tentando fazer?

$ awk '{vals[$2 FS $3] = vals[$2 FS $3] OFS $1} END{for (key in vals) print key vals[key]}' file
Apples Red Sample_1 Sample_2 Sample_3 Sample_4 Sample_5
Apples Green Sample_6 Sample_7 Sample_8 Sample_9 Sample_10
Apples Yellow Sample_11 Sample_12 Sample_13 Sample_14 Sample_15

ou talvez isso?

$ awk -v fruit='Apples' -v color='Green' '($2==fruit) && ($3==color)' file
Sample_6    Apples  Green
Sample_7    Apples  Green
Sample_8    Apples  Green
Sample_9    Apples  Green
Sample_10   Apples  Green

Responder2

Este é um exemplo simples de script gawk que analisa sua entrada e gera uma transposição dos dados que parece adequada às suas necessidades.

#!/usr/bin/gawk -f

# Checks if type (column 2) or subtype (column 3) are 
# different from previous line.
(type != $2) || (subtype != $3) {
    # Prints the start of a new output line.
    # The NR!=1 check avoids that a new line is 
    # printed on the first line.
    printf("%s%s\t%s\t", (NR!=1)?"\n":"", $2, $3);
    type=$2;
    subtype=$3
}
{
    # Prints all sample (column 1) values on the 
    # current output line.
    printf("\"%s\" ", $1);
}
# prints a new line at the end of file.
END{
    print "";
}

A saída script.awk < input.lstsegue. Onde script.awkestá o script anterior e input.lstseu exemplo de entrada.

Apples  Red     "Sample_1" "Sample_2" "Sample_3" "Sample_4" "Sample_5" 
Apples  Green   "Sample_6" "Sample_7" "Sample_8" "Sample_9" "Sample_10" 
Apples  Yellow  "Sample_11" "Sample_12" "Sample_13" "Sample_14" "Sample_15" 

A saída do script pode ser facilmente manipulada da seguinte maneira.

script.awk < input.lst | while read TYPE SUBTYPE LIST
do 
    echo $TYPE
    echo $SUBTYPE
    for ITEM in $LIST
    do  
        echo execute some command on $ITEM where type is $TYPE and subtype is $SUBTYPE
    done 
done

Observe que este script é muito difícil. Por exemplo, não há tratamento de erros nem verificação de espaços em branco ou caracteres especiais na entrada.

Responder3

Tentei com o script abaixo e funcionou bem

for i in "Apples"; do for j in "Red" "Green" "Yellow"; do awk -v i="$i" -v j="$j" 'BEGIN{print "Below are table contains" " " i " and " " " j}$2==i && $NF==j{print $0}' filename; done; done

saída

Below are table contains Apples and  Red
Sample_1    Apples  Red
Sample_2    Apples  Red
Sample_3    Apples  Red
Sample_4    Apples  Red
Sample_5    Apples  Red
Below are table contains Apples and  Green
Sample_6    Apples  Green
Sample_7    Apples  Green
Sample_8    Apples  Green
Sample_9    Apples  Green
Sample_10   Apples  Green
Below are table contains Apples and  Yellow
Sample_11   Apples  Yellow
Sample_12   Apples  Yellow
Sample_13   Apples  Yellow
Sample_14   Apples  Yellow
Sample_15   Apples  Yellow

informação relacionada