Tengo tres marcos de datos:
Marco de datos 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
Marco de datos 2
chr start end Id chr1 401 800 SN_2 chr1 801 1200 SN_3 chr1 1201 1600 SN_4
Marco de datos 3
chr start end Id chr1 1201 1600 SN_4 chr1 1601 2000 SN_5 chr1 2001 2400 SN_6
y me gustaría obtener un marco de datos final donde, de acuerdo con la cuarta columna del primer marco de datos, se informará una coincidencia o no coincidencia en relación con la cuarta columna del segundo y tercer marco de datos. En un nuevo marco de datos, si hay una coincidencia, se informará la misma identificación, pero en caso de que haya una coincidencia, el nombre de la identificación se reemplazará con un NA. Quizás simplemente escribir entradas y salidas sea más fácil de entender. Algo como esto:
Salida deseable:
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
Lo intenté con el comando join en Unix pero no puedo comparar marcos de datos de diferentes tamaños. Cualquier idea será muy apreciada.
Respuesta1
awksolución:
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
La salida:
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
ydf1
son tu 2.º, 3.º y 1.ºmarco de datosarchivos respectivamenteFILENAME
- variable incorporada que apunta al nombre del archivo actualmente procesadoARGV
- variable incorporada que apunta a todos los argumentos pasados al script awk. es decir,ARGV[1]
contienedf2
FILENAME == ARGV[1] && NR>1
- encontrar el primer archivo (es decirdf2
) a partir de la segunda líneadf2[$2,$3,$4]
- capturar valores cruciales de "Marco de datos 2"como clave de matrizdf2
FILENAME == ARGV[2] && FNR>1
- encontrar el segundo archivo (es decirdf3
) a partir de la segunda líneadf3[$2,$3,$4]
- capturar valores cruciales de "Marco de datos 3"como clave de matrizdf3
FILENAME == ARGV[3]
- encontrar el tercer archivo (es decirdf1
), el principalMarco de datos
Respuesta2
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
Funcionamiento
- El orden de las entradas es: marco de datos3, marco de datos2 y marco de datos1.
- Suponiendo que el marco de datos1 tiene las cuartas columnas completas, IOW, no falta ninguna.
- Invocamos
Perl
en modo lectura de línea+autosplit:perl -lane
- Durante el tiempo que se lee el tercer fotograma, @ARGV tiene 2 elementos, durante el segundo fotograma leído hay 1 elemento y 0 durante el tercer fotograma.
- Completamos un hash,
%h
cuyas claves son los campos 2.º y 3.º,$F[1],$F[2]
y los valores son referencias de matriz anónimas, por lo que se denominan:$h{...}[...]
. - Durante el tiempo del primer marco de datos (@ARGV que tiene 0 elementos), imprimimos cada línea con el contenido del primer marco de datos y determinamos si los elementos de la matriz existen o no para el segundo/tercer marco para el segundo actual correspondiente. /3er campos.