Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

273
Views
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 answers
Answer question

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 Report

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 Report

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!