Cómo transformar múltiples columnas en lign sucesivas en awk
Tengo un archivo A.txt (sep = "\ t", la primera columna está vacía):
Cycle A1 A2 B1
1 4 5 2
2 7 3 4
3 3 2 5
Y quiero transformar este archivo en un nuevo archivo B.txt (sep = "\ t"):
Well Cycle Value
A1 1 4
A1 2 7
A1 3 3
A2 1 5
A2 2 3
A2 3 2
B1 1 2
B1 2 4
B1 3 5
Intenté algo con: awk '{for (i = 1; i <= NF; i ++) print $ i}' pero no pude entenderlo. ¿Alguien tiene idea de cómo hacer esto? Gracias
Respuestas
No awk, pero usando Miller , dado
$ cat file
Cycle A1 A2 B1
1 4 5 2
2 7 3 4
3 3 2 5
luego
$ mlr --pprint --ifs tab reshape -i A1,A2,B1 -o Well,Value then sort -f Well then reorder -f Well file
Well Cycle Value
A1 1 4
A1 2 7
A1 3 3
A2 1 5
A2 2 3
A2 3 2
B1 1 2
B1 2 4
B1 3 5
Puede omitir el sortpaso si no es un requisito.
El reshapecomando Miller también puede aceptar una expresión regular para la selección de campos, ej.
reshape -r '[A-Z][1-9]' -o Well,Value
Primero cargamos el archivo en una matriz de matriz AoA[colidx, rowidx] Luego, al final del bloque de archivo, reestructuramos estos datos en el formato que deseamos.
Nota:
- El separador de campos es
\t+caminar sobre pestañas consecutivas y no recibir campos vacíos. - la
gsub()parte consiste en eliminar las n pestañas iniciales al final. - Este código se encargará de tantas columnas y filas como tenga el archivo (si la memoria lo permite)
awk -F '\t+' '
gsub(/^\t|\t$/, "") {$1=$1} NR==1 {header = "Well" OFS $1 OFS "Value"}
{
for(i=1; i<=NF; i++) {
AoA[i, NR] = $(i)
}
}
END {
print header
for(col=2; col<=NF; col++) {
for(row=2; row<=NR; row++) {
well = AoA[col, 1]
cycle = AoA[1, row]
value = AoA[col, row]
print well, cycle, value
}
}
}
' OFS='\t' - | column -t
Resultados:
Well Cycle Value
A1 1 4
A1 2 7
A1 3 3
A2 1 5
A2 2 3
A2 3 2
B1 1 2
B1 2 4
B1 3 5
Aquí hay un enfoque (bastante burdo) que requiere que los encabezados sean estáticos y conocidos de antemano, y que no se ordena bien:
$ awk -F'\t' -v OFS="\t" 'BEGIN{print "Well","Cycle","Value"} NR>1{ cycle[NR]=$2;
a1[NR]=$3; a2[NR]=$4;
b1[NR]=$5;
}
END{
for(line in cycle){
print "A1",cycle[line],a1[line];
print "A2",cycle[line],a2[line];
print "B1",cycle[line],b1[line]
}
}' file
Well Cycle Value
A1 1 4
A2 1 5
B1 1 2
A1 2 7
A2 2 3
B1 2 4
A1 3 3
A2 3 2
B1 3 5
Si necesita ordenar bien, puede usar el aún más crudo:
$ awk -F'\t' -vOFS="\t" 'BEGIN{print "Well","Cycle","Value"}
NR>1{
cycle[NR]=$2; a1[NR]=$3;
a2[NR]=$4; b1[NR]=$5;
}
END{
for(line in cycle){
print "A1",cycle[line],a1[line];
}
for(line in cycle){
print "A2",cycle[line],a2[line];
}
for(line in cycle){
print "B1",cycle[line],b1[line]
}
}' file
Well Cycle Value
A1 1 4
A1 2 7
A1 3 3
A2 1 5
A2 2 3
A2 3 2
B1 1 2
B1 2 4
B1 3 5