Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

274
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda