Eu tenho três quadros de dados:
Quadro de dados 1
chr start end Id chr1 1 400 SN_1 chr1 401 800 SN_2 chr1 801 1200 SN_3 chr1 1201 1600 SN_4 chr1 1601 2000 SN_5 chr1 2001 2400 SN_6 chr1 2401 2800 SN_7
Quadro de dados 2
chr start end Id chr1 401 800 SN_2 chr1 801 1200 SN_3 chr1 1201 1600 SN_4
Quadro de dados 3
chr start end Id chr1 1201 1600 SN_4 chr1 1601 2000 SN_5 chr1 2001 2400 SN_6
e gostaria de obter um data frame final onde, de acordo com a 4ª coluna do 1º data frame, será reportada uma correspondência ou não correspondência em relação à 4ª coluna do 2º e 3º data frame. Em um novo quadro de dados Se houver uma correspondência, o mesmo Id será relatado, mas caso haja uma correspondência, o nome do Id será substituído por um NA. Talvez apenas escrever a entrada e a saída seja mais fácil de entender. Algo assim:
Saída desejável:
chr start end Id Id Id chr1 1 400 SN_1 NA NA chr1 401 800 SN_2 SN_2 NA chr1 801 1200 SN_3 SN_3 NA chr1 1201 1600 SN_4 SN_4 SN_4 chr1 1601 2000 SN_5 NA SN_5 chr1 2001 2400 SN_6 NA SN_6 chr1 2401 2800 SN_7 NA NA
Eu tentei com o comando join in unix, mas não consigo comparar quadros de dados de tamanhos diferentes. Qualquer ideia será muito apreciada.
Responder1
estranhosolução:
awk 'FILENAME == ARGV[1] && NR>1{ df2[$2,$3,$4] }
FILENAME == ARGV[2] && FNR>1{ df3[$2,$3,$4] }
FILENAME == ARGV[3]{ if(FNR == 1) { printf("%s\t%s\t%s\n",$0,$NF,$NF) }
else { printf("%s\t%s\t%s\n",$0, (($2,$3,$4) in df2)? $NF :"NA",(($2,$3,$4) in df3)? $NF :"NA")}
}' df2 df3 df1 | column -t
A saída:
chr start end Id Id Id
chr1 1 400 SN_1 NA NA
chr1 401 800 SN_2 SN_2 NA
chr1 801 1200 SN_3 SN_3 NA
chr1 1201 1600 SN_4 SN_4 SN_4
chr1 1601 2000 SN_5 NA SN_5
chr1 2001 2400 SN_6 NA SN_6
chr1 2401 2800 SN_7 NA NA
df2
,df3
edf1
são seu 2º, 3º e 1ºquadro de dadosarquivos respectivamenteFILENAME
- variável interna apontando para o nome do arquivo atualmente processadoARGV
- variável interna apontando para todos os argumentos passados para o script awk. ou seja,ARGV[1]
contémdf2
FILENAME == ARGV[1] && NR>1
- encontrando o primeiro arquivo (ou sejadf2
) começando na 2ª linhadf2[$2,$3,$4]
- capturar valores cruciais de "Quadro de dados 2" como chave do arraydf2
FILENAME == ARGV[2] && FNR>1
- encontrando o segundo arquivo (ou sejadf3
) começando na segunda linhadf3[$2,$3,$4]
- capturar valores cruciais de "Quadro de dados 3" como chave do arraydf3
FILENAME == ARGV[3]
- encontrando o terceiro arquivo (ou sejadf1
), o principalQuadro de dados
Responder2
perl -lane '$,="\t";
!@ARGV and $. == 1 and print($_, qw/Id/x2),next;
$h{$F[1],$F[2]}->[@ARGV] = $F[3];
!@ARGV and print $_, map { $h{$F[1],$F[2]}->[$_] // q/NA/ } 1..2;
$. = 0 if eof;
' file3 file2 file1
Resultados
chr start end Id Id Id
chr1 1 400 SN_1 NA NA
chr1 401 800 SN_2 SN_2 NA
chr1 801 1200 SN_3 SN_3 NA
chr1 1201 1600 SN_4 SN_4 SN_4
chr1 1601 2000 SN_5 NA SN_5
chr1 2001 2400 SN_6 NA SN_6
chr1 2401 2800 SN_7 NA NA
Funcionamento
- A ordem das entradas é: dataframe3, dataframe2 e dataframe1.
- Supondo que o dataframe1 tenha todas as quartas colunas preenchidas, IOW, nenhuma faltando.
- Invocamos
Perl
no modo line-read-in+autosplit:perl -lane
- Durante o tempo de leitura do 3º quadro, @ARGV possui 2 elementos, durante a leitura do 2º quadro tem 1 elemento e 0 durante o 3º quadro.
- Preenchemos um hash,
%h
, cujas chaves são o 2º + 3º campos,$F[1],$F[2]
e os valores são referências anônimas de array, portanto referidos como:$h{...}[...]
. - Durante o tempo do 1º quadro de dados (@ARGV tendo 0 elementos), estamos imprimindo cada linha com o conteúdo do 1º quadro de dados e determinando se os elementos da matriz existem ou não para os 2º/3º quadros para o 2º quadro atual correspondente /3º campos.