valor una ubican rango posicion otra obtener nombre las indice hojas funcion fila donde diversas devolver columna coincidir celda calculo buscar barra bash awk subset bioinformatics cut

bash - ubican - obtener fila y columna de una celda excel



Subconjunto de un archivo por números de fila y columna (5)

No quitar nada de las dos respuestas excelentes. Solo porque este problema involucre un gran conjunto de datos, estoy publicando una combinación de 2 respuestas para acelerar el procesamiento.

awk -v cols="$(<subsetCols.txt)" -v rows="$(<subsetRows.txt)" '' BEGIN { n = split(cols, c, /,/) split(rows, r, /,/) for (i in r) row[r[i]] } (NR-1) in row { for (i=1; i<=n; i++) printf "%s%s", $(c[i]+1), (i<n?OFS:ORS) }'' inputFile.txt

PD: Esto también debería funcionar con versiones awk más antiguas o awk no gnu.

Queremos subconjuntar un archivo de texto en filas y columnas, donde las filas y los números de las columnas se leen desde un archivo. Excluyendo encabezado (fila 1) y nombres de fila (columna 1).

archivo de texto delimitado por tabulación inputFile.txt

header 62 9 3 54 6 1 25 1 2 3 4 5 6 96 1 1 1 1 0 1 72 3 3 3 3 3 3 18 0 1 0 1 1 0 82 1 0 0 0 0 1 77 1 0 1 0 1 1 15 7 7 7 7 7 7 82 0 0 1 1 1 0 37 0 1 0 0 1 0 18 0 1 0 0 1 0 53 0 0 1 0 0 0 57 1 1 1 1 1 1

subsetCols.txt Coma separada sin espacios, una fila, números ordenados. En datos reales tenemos 500K columnas, y necesitamos subconjunto ~ 10K.

1,4,6

subsetRows.txt Separadas por comas sin espacios, una fila, números ordenados. En datos reales tenemos 20K filas, y necesitamos subconjuntos alrededor de ~ 300.

1,3,7

Solución actual usando corte y awk loop ( Publicación relacionada: Seleccionar filas usando awk ):

# define vars fileInput=inputFile.txt fileRows=subsetRows.txt fileCols=subsetCols.txt fileOutput=result.txt # cut columns and awk rows cut -f2- $fileInput | cut -f`cat $fileCols` | sed ''1d'' | awk -v s=`cat $fileRows` ''BEGIN{split(s, a, ","); for (i in a) b[a[i]]} NR in b'' > $fileOutput

Archivo de salida: result.txt

1 4 6 3 3 3 7 7 7

Pregunta:
Esta solución funciona bien para archivos pequeños, para archivos más grandes 50K filas y 200K columnas, está tardando demasiado, 15 minutos más, aún en ejecución. Creo que cortar las columnas funciona bien, seleccionar las filas es el lento.

¿Alguna mejor manera?

Información real de archivos de entrada:

# $fileInput: # Rows = 20127 # Cols = 533633 # Size = 31 GB # $fileCols: 12000 comma separated col numbers # $fileRows: 300 comma separated row numbers

Más información sobre el archivo: el archivo contiene datos de genotipo GWAS . Cada fila representa una muestra (individual) y cada columna representa SNP . Para análisis adicionales basados ​​en regiones, necesitamos subconjuntos de muestras (filas) y SNP (columnas), para hacer que los datos sean más manejables (pequeños) como entrada para otros softwares estadísticos como r .

Sistema:

$ uname -a Linux nYYY-XXXX ZZZ Tue Dec 18 17:22:54 CST 2012 x86_64 x86_64 x86_64 GNU/Linux

Actualización: La solución proporcionada a continuación por @JamesBrown fue mezclar los pedidos de columnas en mi sistema, ya que estoy usando una versión diferente de awk, mi versión es: GNU Awk 3.1.7


Python tiene un módulo csv. Usted lee una fila en una lista, imprime las columnas deseadas para stdout, enjuague, lave, repita.

Esto debería cortar columnas de 20,000 a 30,000.

import csv with open(''foo.txt'') as f: gwas = csv.reader(f, delimiter='','', quoting=csv.QUOTE_NONE) for row in gwas: print(row[20001:30001]


Uno en Gnu awk versión 4.0 o posterior ya que el orden de las columnas se basa en y PROCINFO["sorted_in"] . Los números de fila y col se leen de los archivos:

$ awk '' BEGIN { PROCINFO["sorted_in"]="@ind_num_asc"; } FILENAME==ARGV[1] { # process rows file n=split($0,t,","); for(i=1;i<=n;i++) r[t[i]] } FILENAME==ARGV[2] { # process cols file m=split($0,t,","); for(i=1;i<=m;i++) c[t[i]] } FILENAME==ARGV[3] && ((FNR-1) in r) { # process data file for(i in c) printf "%s%s", $(i+1), (++j%m?OFS:ORS) }'' subsetRows.txt subsetCols.txt inputFile.txt 1 4 6 3 3 3 7 7 7

El aumento del rendimiento podría provenir de mover el bloque de procesamiento ARGV[3] a la parte superior berore 1 y 2 y agregar uno al next de su extremo.


para refinar la solución de @anubhava, podemos eliminar la búsqueda de más de 10k valores para cada fila para ver si estamos en la fila correcta al aprovechar el hecho de que la entrada ya está ordenada

awk -v cols="$(<subsetCols.txt)" -v rows="$(<subsetRows.txt)" '' BEGIN { n = split(cols, c, /,/) split(rows, r, /,/) j=1; } (NR-1) == r[j] { j++ for (i=1; i<=n; i++) printf "%s%s", $(c[i]+1), (i<n?OFS:ORS) }'' inputFile.txt


Aunque en Si los lenguajes de programación eran países, ¿qué país representaría cada idioma? ellos dijeron eso...

Awk: Corea del Norte. Obstinadamente se resiste al cambio, y sus usuarios parecen ser antinaturalmente aficionados por razones que solo podemos especular.

... cada vez que te veas cantar sed, cortar, grep, awk, etc., detente y dite a ti mismo: ¡ awk puede hacerlo solo!

Entonces, en este caso, se trata de extraer las filas y las columnas (ajustarlas para excluir el encabezado y la primera columna) y luego simplemente almacenar en búfer el resultado para finalmente imprimirlo.

awk -v cols="1 4 6" -v rows="1 3 7" '' BEGIN{ split(cols,c); for (i in c) col[c[i]] # extract cols to print split(rows,r); for (i in r) row[r[i]] # extract rows to print } (NR-1 in row){ for (i=2;i<=NF;i++) (i-1) in col && line=(line ? line OFS $i : $i); # pick columns print line; line="" # print them }'' file

Con su archivo de muestra:

$ awk -v cols="1 4 6" -v rows="1 3 7" ''BEGIN{split(cols,c); for (i in c) col[c[i]]; split(rows,r); for (i in r) row[r[i]]} (NR-1 in row){for (i=2;i<=NF;i++) (i-1) in col && line=(line ? line OFS $i : $i); print line; line=""}'' file 1 4 6 3 3 3 7 7 7

Con su archivo de muestra, y las entradas como variables, divida en coma:

awk -v cols="$(<$fileCols)" -v rows="$(<$fileRows)" ''BEGIN{split(cols,c, /,/); for (i in c) col[c[i]]; split(rows,r, /,/); for (i in r) row[r[i]]} (NR-1 in row){for (i=2;i<=NF;i++) (i-1) in col && line=(line ? line OFS $i : $i); print line; line=""}'' $fileInput

Estoy bastante seguro de que esto será mucho más rápido. Puede, por ejemplo, comprobar Eliminar duplicados del archivo de texto basado en el segundo archivo de texto para algunos puntos de referencia que comparan el rendimiento de awk sobre grep y otros.

Mejor,
Kim Jong-un