Contando valores entre dos valores definidos por dos columnas

Contando valores entre dos valores definidos por dos columnas

Tengo datos almacenados en tres columnas como esta:

3651 3631 3913
3667 3996 4276
3674 4486 4605
3707 4706 5095
3720 5174 5326
3750 5439 5899
3755 5928 6263
3767 6437 7069
3779 7157 7232
3882 7384 7450
3886 7564 7649
3900 7762 7835
4006 7942 7987
4015 8236 8325
4026 8417 8464
4065 8571 8737
4156 6790 7069
4493 7157 7450
4541 7564 7649
4551 7762 7835
4597 7942 7987
4756 8236 8325
4776 8417 8464

donde la primera columna es un valor específico, la segunda columna es el inicio y la tercera columna es el final. Hay 825849 líneas en la primera columna y 58386 en la segunda y tercera. Necesito contar los valores desde el primero si están entre el inicio y el final.

Sé que en mi archivo los primeros 12 valores específicos de la columna número 1 están entre el primer inicio y el final, los 5 siguientes están entre el segundo inicio y el final, y así sucesivamente. Necesito revisar el archivo completo. Lo he probado con esto y funciona pero muy lento:

coords='final_exons.txt'

snp=( $( cat $coords | awk '{print $1}') )
exon_start=( $( cat $coords | awk '{print $2}') )
exon_end=( $( cat $coords | awk '{print $3}') )

i=0
counter=0
for value in ${exon_end[@]}; do
    new_val=$counter
    counter=0
    let "i++"
    for snps in ${snp[@]}; do

        if [[ $value > $snps ]]; then
            #statements
            let "counter++"
            #$counter=$(echo "scale=2; $counter-$new_val" | bc)
        else
            #$new_val=$(echo "scale=2; $counter-$")
            break
        fi
    done
    #echo "NOWENOWE $new_val "
    #echo "COUNTER $value : $counter "
    final=$(echo "scale=2; sqrt(($counter-$new_val)^2)" | bc)
    echo "Exon $i : $final SNPs"
done

Gracias de antemano por cualquier sugerencia y consejo.

enlace para datos completos

Respuesta1

  1. Coloque cada valor en una línea, pero marque "inicio" y "fin" agregándolos So E. Ahora ordena los valores numéricamente. Obtendrías algo como
3631S
3651
3667
...
3900
3913E
3996S
4006
...
  1. Cuente las ocurrencias entre Say un Evalor terminado.

¡Escribe el guión y sé feliz!

awk '
    {print $1} 
    $3!="" {print $2"S"; print $3"E"} 
' final_exons.txt | sort -n | awk '
    !/E|S/ {count++; next}
    /S/ {count=0; next}
    /E/ {print line++": "count}'

La primera awky sortrealiza el paso 1. Hay una $3!=""prueba (también podría ser $2!="") porque hay más líneas en la 1ª columna que en la 2ª o 3ª.

El segundo awkcorresponde al paso 2. Reinicia el contador si lee líneas con S, lo incrementa si la línea no tiene marcador y lo imprime (junto con el número de línea) si lee la línea con E.

El resultado cuando se ejecuta en el archivo de muestra que proporcionó es 0: 12; 1: 5; 2: 4; 3: 2; ...; 22: 0.

Respuesta2

Me vendría bien un awk:

awk '{if( ($1 > $2) && ($1 < $3) ){print NR" "$1" "$2" "$3}}' final_exons.txt

Pero si col1 y (col2 y col3) se tratan por separado, es mejor separarlos en archivos separados. O coloque los datos en la base de datos y luego realice la prueba de intervalo dentro de ella. Pero la forma más eficiente podría ser cargar los datos en la matriz normal y realizar los bucles de prueba en algún otro lenguaje de programación (php, python, perl...)

información relacionada