Estoy tratando de filtrar un archivo basado en dos columnas de otro. El problema es que awk no está diferenciando, por ejemplo, este intervalo 70083 83083, de la posición 7323573 (ver más abajo). El objetivo es recuperar el valor del archivo 1 que se encuentra en la columna 5 del archivo 2. El archivo 1 tiene solo una posición en la columna 3, por ejemplo: 51476, y el archivo 2 tiene un intervalo representado por las columnas 3 y 4. Al final, necesito el archivo 1 con los valores respectivos de la columna 5 (ver salida).

Archivo 1

rs187298206 chr1 51476 0.0072 0.201426626822702
rs116400033 chr1 51479 0.2055 1.18445621536109
rs62637813 chr1 52058 0.0587 0.551216300225955
rs190291950 chr1 52144 -4e-04 0.036575951491895
rs150021059 chr1 52238 0.3325 1.70427928591544
rs140052487 chr1 54353 0.003 0.12778378962414
rs146477069 chr1 54421 0.1419 0.924336309646664
rs141149254 chr1 54490 0.1767 1.06786868821145
rs2462492 chr1 54676 0.0819 0.664355314594874
rs143174675 chr1 54753 0.026 0.356836206987615
rs3091274 chr1 55164 0.3548 1.80091078751368
rs10399749 chr1 55299 0.0309 0.389748348495465
rs182462964 chr1 55313 2e-04 0.0877969207975495
rs3107975 chr1 55326 0.0237 0.344080010917931
rs142800240 chr1 7323573 -6e-04 0.0361473609720785

Archivo 2

51083_1 chr1 51083 56000 -0.177152387075888 0.172569306719619
57083_1 chr1 57083 60083 -0.0524335467819781 0.130497858911419
60083_1 chr1 70083 83083 -0.0332555672564894 0.124932838766226
525083_1 chr1 525083 528083 0.291406335374442 0.0577249392691202
528083_1 chr1 528083 531083 0.291406335374442 0.0577249392691202
531083_1 chr1 531083 534083 0.291406335374442 0.0577249392691202
534083_1 chr1 534083 537083 0.291406335374442 0.0577249392691202
534083_1 chr1 534083 537083 0.441406335374442 0.0577249392691202

Lo que obtengo con este script:

awk '
NR == FNR {score[$3] = $1 FS $2 FS $3 FS $4; next}
{
for (key in score)
if (key > $3 && key < $4)
print score[key], $5
}
' file1 file2 > output

Salida

 rs140052487 chr1 54353 0.003 -0.177152387075888
 rs150021059 chr1 52238 0.3325 -0.177152387075888
 rs3107975 chr1 55326 0.0237 -0.177152387075888
 rs3091274 chr1 55164 0.3548 -0.177152387075888
 rs187298206 chr1 51476 0.0072 -0.177152387075888
 rs116400033 chr1 51479 0.2055 -0.177152387075888
 rs10399749 chr1 55299 0.0309 -0.177152387075888
 rs146477069 chr1 54421 0.1419 -0.177152387075888
 rs190291950 chr1 52144 -4e-04 -0.177152387075888
 rs182462964 chr1 55313 2e-04 -0.177152387075888
 rs141149254 chr1 54490 0.1767 -0.177152387075888
 rs62637813 chr1 52058 0.0587 -0.177152387075888
 rs143174675 chr1 54753 0.026 -0.177152387075888
 rs2462492 chr1 54676 0.0819 -0.177152387075888
 rs142800240 chr1 7323573 -6e-04 -0.0332555672564894 <- this should not appear
1
Jontexas 27 ene. 2016 a las 19:16

2 respuestas

La mejor respuesta
awk '     
NR == FNR {score[$3] = $1 FS $2 FS $3 FS $4; next}
{
for (key in score)
if (key+0 > $3 && key+0 < $4)
print score[key], $5
}
' fst.txt tajima.txt > output

Me da

[/tmp]$ cat output
rs182462964 chr1 55313 2e-04 -0.177152387075888
rs190291950 chr1 52144 -4e-04 -0.177152387075888
rs62637813 chr1 52058 0.0587 -0.177152387075888
rs146477069 chr1 54421 0.1419 -0.177152387075888
rs140052487 chr1 54353 0.003 -0.177152387075888
rs3107975 chr1 55326 0.0237 -0.177152387075888
rs187298206 chr1 51476 0.0072 -0.177152387075888
rs141149254 chr1 54490 0.1767 -0.177152387075888
rs10399749 chr1 55299 0.0309 -0.177152387075888
rs3091274 chr1 55164 0.3548 -0.177152387075888
rs143174675 chr1 54753 0.026 -0.177152387075888
rs2462492 chr1 54676 0.0819 -0.177152387075888
rs150021059 chr1 52238 0.3325 -0.177152387075888
rs116400033 chr1 51479 0.2055 -0.177152387075888

Para forzar la interpretación como un número, agregue 0. desde la página de manual de awk.

3
Calvin Taylor 27 ene. 2016 a las 16:47

Puedo reproducir su problema en Mac OS X 10.11.3 con el BSD del sistema awk.

El problema tiene que ver con la comparación entre cadenas y números; awk parece estar tratando el key como una cadena y está haciendo una comparación de cadenas en lugar de una comparación numérica.

Lo he forzado brutalmente a tratar la comparación numéricamente con:

awk '
NR == FNR {score[$3] = $1 FS $2 FS $3 FS $4; next}
{
    for (key in score)
    {
        if (key+0 > $3+0 && key+0 < $4+0)
        {
            #print "==", key, $3, $4
            #if (key > $3) print key, ">", $3
            #if (key < $4) print key, "<", $4
            print score[key], $5
        }
    }
}
' file1 file2

Puedes ver el '+0' para forzar a awk a tratar las cosas como números. (El análogo para forzar a awk a tratar un valor como una cadena es, por ejemplo, key "", que concatena una cadena vacía con el valor (cadena) de key).

Con sus datos de muestra, obtengo el resultado:

rs140052487 chr1 54353 0.003 -0.177152387075888
rs150021059 chr1 52238 0.3325 -0.177152387075888
rs3107975 chr1 55326 0.0237 -0.177152387075888
rs3091274 chr1 55164 0.3548 -0.177152387075888
rs187298206 chr1 51476 0.0072 -0.177152387075888
rs116400033 chr1 51479 0.2055 -0.177152387075888
rs10399749 chr1 55299 0.0309 -0.177152387075888
rs146477069 chr1 54421 0.1419 -0.177152387075888
rs190291950 chr1 52144 -4e-04 -0.177152387075888
rs182462964 chr1 55313 2e-04 -0.177152387075888
rs141149254 chr1 54490 0.1767 -0.177152387075888
rs62637813 chr1 52058 0.0587 -0.177152387075888
rs143174675 chr1 54753 0.026 -0.177152387075888
rs2462492 chr1 54676 0.0819 -0.177152387075888

Parte de la salida de depuración, que delató el juego, fue:

== 54676 51083 56000
54676 > 51083
54676 < 56000
rs2462492 chr1 54676 0.0819 -0.177152387075888
== 7323573 70083 83083
7323573 > 70083
7323573 < 83083
rs142800240 chr1 7323573 -6e-04 -0.0332555672564894

Para las cadenas de 5 dígitos, la comparación resultó ser la misma que una comparación numérica. Para el otro, no fue así. También debo señalar que las partes $3+0 y $4+0 probablemente no son esenciales. Los tenía cuando me mostraron la salida de depuración, pero las pruebas solo comenzaron a funcionar cuando agregué 0 al key. Probablemente no necesite agregar 0 a $3 o $4, por lo tanto.

1
Jonathan Leffler 27 ene. 2016 a las 16:49