Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

266
Vistas
Agregar valores separados por comas dentro de una columna

Hola, tengo un formato de archivo (TSV) como este

 Name type Age Weight Height Xxx M 12,34,23 50,30,60,70 4,5,6,5.5 Yxx F 21,14,32 40,50,20,40 3,4,5,5.5

Me gustaría agregar todos los valores en Edad, Peso y Altura y agregar una columna después de esto, luego también un porcentaje, como Total_Height/Total_Weight (awk '$0=$0"\t"(NR==1?"Percentage" :$8/$7)'). Tengo un gran conjunto de datos y no es posible hacerlo con Excel.

Me gusta esto

 Name type Age Weight Height Total_Age Total_Weight Total_Height Percentage Xxx M 12,34,23 50,30,60,70 4,5,6,5.5 69 210 20.5 0.097 Yxx F 21,14,32 40,50,20,40 3,4,5,5.5 67 150 17.5 0.11
over 4 years ago · Santiago Trujillo
5 Respuestas
Responde la pregunta

0

Usando cualquier awk en cualquier shell en cada cuadro de Unix y sin crear nuevos campos en cada registro (lo cual es ineficiente ya que hace que awk reconstruya el registro cada vez que cambia un campo) y sin actualizar el registro de entrada (que es ineficiente como hace que awk vuelva a dividir el registro en campos cada vez que cambia el registro) y está diseñado para funcionar para cualquier cantidad de columnas de entrada de valor en cualquier orden:

 $ cat tst.awk BEGIN { FS=OFS="\t" } { printf "%s%s", $0, OFS } NR==1 { for (i=3; i<=NF; i++) { printf "Total_%s%s", $i, OFS tags[i] = $i } print "Percentage" next } { delete tot for (i=3; i<=NF; i++) { tag = tags[i] n = split($i,vals,",") for (j in vals) { tot[tag] += vals[j] } printf "%s%s", tot[tag], OFS } printf "%0.3f%s", (tot["Weight"] ? tot["Height"] / tot["Weight"] : 0), ORS }

 $ awk -f tst.awk file Name type Age Weight Height Total_Age Total_Weight Total_Height Percentage Xxx M 12,34,23 50,30,60,70 4,5,6,5.5 69 210 20.5 0.098 Yxx F 21,14,32 40,50,20,40 3,4,5,5.5 67 150 17.5 0.117

 $ awk -f tst.awk file | column -t Name type Age Weight Height Total_Age Total_Weight Total_Height Percentage Xxx M 12,34,23 50,30,60,70 4,5,6,5.5 69 210 20.5 0.098 Yxx F 21,14,32 40,50,20,40 3,4,5,5.5 67 150 17.5 0.117

Para mostrar las ventajas funcionales del enfoque anterior, imagine que necesita agregar más valores como ShoeSize y/o reorganizar el orden de las columnas, por ejemplo:

 $ column -t file Name type ShoeSize Height Age Weight Xxx M 12,8,10 4,5,6,5.5 12,34,23 50,30,60,70 Yxx F 9,7,8 3,4,5,5.5 21,14,32 40,50,20,40

Ahora ejecute el script anterior y observe que se Total_ columnas para cada columna original y aún obtiene la misma columna de Percentage de Altura/Peso agregada al final:

 $ awk -f tst.awk file | column -t Name type ShoeSize Height Age Weight Total_ShoeSize Total_Height Total_Age Total_Weight Percentage Xxx M 12,8,10 4,5,6,5.5 12,34,23 50,30,60,70 30 20.5 69 210 0.098 Yxx F 9,7,8 3,4,5,5.5 21,14,32 40,50,20,40 24 17.5 67 150 0.117
over 4 years ago · Santiago Trujillo Denunciar

0

Aquí hay un Ruby que es un poco más fácil para múltiples campos de datos como este:

 ruby -F"\t" -lane ' if ($.==1) puts "Name\ttype\tAge\tWeight\tHeight\tTotal_Age\tTotal_Weight\tTotal_Height\tPercentage" next end fields=$F.clone $F.each{|f| fields.append(f.split(/,/).map(&:to_f).sum) if f[/^[\d,.]+$/] && f[/,/]} fields.append((fields[-1]/fields[-2]).round(3)) puts fields.join("\t")' file | column -t

Huellas dactilares:

 Name type Age Weight Height Total_Age Total_Weight Total_Height Percentage Xxx M 12,34,23 50,30,60,70 4,5,6,5.5 69.0 210.0 20.5 0.098 Yxx F 21,14,32 40,50,20,40 3,4,5,5.5 67.0 150.0 17.5 0.117

La ventaja aquí es que las sumas de columnas de n.nn,n.nn,... se agregan de manera flexible al final de la fila en el orden en que se encuentran.

over 4 years ago · Santiago Trujillo Denunciar

0

Usaría la split de funciones de GNU AWK para esta tarea de la siguiente manera. Considere seguir un ejemplo simple, deje que el contenido de file.txt sea

 Name type Age Weight Height Xxx M 12,34,23 50,30,60,70 4,5,6,5.5 Yxx F 21,14,32 40,50,20,40 3,4,5,5.5

luego

 awk 'BEGIN{OFS="\t"}NR==1{print "Age","Total"}NR>1{totalage=0;split($3,ages,",");for(a in ages){totalage+=ages[a]};print $3,totalage}' file.txt

producción

 Age Total 12,34,23 69 21,14,32 67

Explicación: en primer lugar, informé a GNU AWK para usar la pestaña como separador de campo de salida ( OFS ), luego, para la primera línea, totalage encabezados, para cada línea siguiente: establezco el valor total en 0 , divido el contenido de la tercera columna en ages de matriz en , , transversal dicha matriz obtiene la suma de sus valores y luego print el contenido de la tercera columna y la suma. Tenga en cuenta que

Antes de dividir la cadena, split() elimina cualquier elemento previamente existente en la matriz de matrices y seps .

Por lo tanto, no requiere reinicio a diferencia de la variable totalage .

(probado en gawk 4.2.1)

over 4 years ago · Santiago Trujillo Denunciar

0

Con sus muestras mostradas, intente seguir el código.

 awk ' FNR==1{ print $0,"Total_Age Total_Weight Total_Height Percentage" next } FNR>1{ totAge=totWeight=totHeight=0 split($3,tmp,",") for(i in tmp){ totAge+=tmp[i] } split($4,tmp,",") for(i in tmp){ totWeight+=tmp[i] } split($5,tmp,",") for(i in tmp){ totHeight+=tmp[i] } $(NF+1)=totAge $(NF+1)=totWeight $(NF+1)=totHeight $(NF+1)=$(NF-1)==0?"N/A":$NF/$(NF-1) } 1' Input_file | column -t

O agregando una versión un poco corta del código awk anterior:

 awk ' BEGIN{OFS="\t"} FNR==1{ print $0,"Total_Age Total_Weight Total_Height Percentage" next } FNR>1{ totAge=totWeight=totHeight=0 split($3,tmp,",") for(i in tmp){ totAge+=tmp[i] } split($4,tmp,",") for(i in tmp){ totWeight+=tmp[i] } split($5,tmp,",") for(i in tmp){ totHeight+=tmp[i] } $(NF+1)=totAge OFS totWeight OFS totHeight $0=$0 $(NF+1)=( $(NF-1)==0 ? "N/A" : $NF/$(NF-1) ) } 1' Input_file | column -t

Explicación: la explicación simple sería tomar la suma de las columnas 3, 4 y 5 y asignarlas a la última columna de la línea. En consecuencia, agregue el valor de la columna que tiene el valor de división de la última y la segunda última columna según la solicitud de OP. Usando column -t para que se vea mejor en la salida.

over 4 years ago · Santiago Trujillo Denunciar

0

Si tiene que hacer las mismas operaciones varias veces, también puede usar una función para sumar los valores de la matriz (dado que los valores son números separados por comas).

Reutilizando algunas partes de la respuesta de @ RavinderSingh13 y un gran agradecimiento a @ Ed Morton por tomarse el tiempo para brindar excelentes comentarios para mejorar el código:

 awk ' function arraySum(field, sum,arr,i) { split(field,arr,",") for (i in arr) sum += arr[i] return sum } FNR==1{ print $0, "Total_Age", "Total_Weight", "Total_Height", "Percentage" next } NR > 1 { sumWeight = arraySum($4) sumHeight = arraySum($5) print $0, arraySum($3), sumWeight, sumHeight, (sumWeight ? sumHeight/sumWeight : 0) }' file | column -t

Producción

 Name type Age Weight Height Total_Age Total_Weight Total_Height Percentage Xxx M 12,34,23 50,30,60,70 4,5,6,5.5 69 210 20.5 0.097619 Yxx F 21,14,32 40,50,20,40 3,4,5,5.5 67 150 17.5 0.116667
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda