¿Cómo agrega columnas desde una hoja de cálculo y luego genera porcentajes en Perl?

Tengo muchos datos en un formato como este.

Amistad Academy District Amistad Academy    596 812 73.4
Andover School District  Andover            39  334 11.7
Ansonia School District  Ansonia High School    427 732 58.3
Ansonia School District  Ansonia Middle School  219 458 47.8
Ansonia School District  Mead School            431 642 67.1
Ansonia School District  Prendergast School 504 787 64

Lo que tengo que hacer es juntar un grupo de distritos escolares y luego tomar la última columna, sumar todos los distritos coincidentes (todos los de Ansonia, por ejemplo) y luego dividir ese número por la suma de la penúltima columna. No tengo problemas para poner los distritos escolares en archivos separados. Eso fue solo un grep. Ahora, sin embargo, estoy atascado y pensando que podría ser más fácil hacerlo en Excel. He estado jugando con soluciones en perl como

  1 #!/opt/local/bin/perl
  2 use strict;
  3 use warnings;
  4 use ARGV::readonly;
  5 
  6 my @data;
  7 my @headers - split ',', <>;
  8 
  9 while (<>) {
 10   my @row = split;
 11   $data[$_] += $row[$_] for (0 .. $#row);
 12 }
 13 
 14 $" = "\t";
 15 print "@headers", "\n";
 16 print "@data";

pero no puedo entender la sintaxis para hacer la suma y la división.

Gracias.

preguntado el 22 de mayo de 12 a las 18:05

¿Esto es tarea? No tenemos ningún problema en ayudar con la tarea, pero especifique si es así, podemos ajustar nuestras respuestas en consecuencia. -

No deberes. Mi esposa es investigadora de una fundación educativa. Tontamente le dije que esto sería mucho más fácil con un guión simple. -

@edward: no te preocupes: le diré que todo fue tu propio trabajo :) -

2 Respuestas

Estás sumando cada columna. Solo quieres sumar dos de ellos. De lo contrario, estás prácticamente allí.

my $sum_last = 0;  # Use better name.
my $sum_penu = 0;  # Use better name.
while (<>) {
   chomp;
   my @row = split /\t/;
   next if $row[0] ne 'Ansonia School District';
   $sum_last += $row[-1];
   $sum_penu += $row[-2];
}

say $sum_last / $sum_penu;

contestado el 22 de mayo de 12 a las 18:05

El programa a continuación seleccionará los valores del archivo y mantendrá los totales acumulados para cada distrito escolar en un hash. El contenido del hash se imprime cuando se han leído todos los datos. Funciona desde el archivo sin filtrar; no es necesario que lo grep en fuentes separadas.

Noté que sus datos parecen estar separados por tabulaciones, y es importante usar split /\t/ para que los campos que contienen caracteres de espacio no se dividan también.

No dice qué significan los datos, por lo que no puedo hacer que el código sea más legible.

Por favor, vuelva a preguntar si tiene más preguntas.

use strict;
use warnings;

open my $fh, '<', 'myfile' or die $!;

scalar <$fh>; # lose header record

my %data;

while (<$fh>) {
  my @fields = split /\t/;
  my $district = shift @fields;
  $data{$district}[0] += $fields[-2];
  $data{$district}[1] += $fields[-1];
}

for my $district (sort keys %data) {
  printf "%s - %f\n", $district, $data{$district}[1] / $data{$district}[0];
}

salida

Andover School District - 0.035030
Ansonia School District - 0.090569

contestado el 22 de mayo de 12 a las 18:05

Hmm, esto no produce errores pero tampoco produce nada más. Cambié myfile al nombre de archivo correcto pero no parece estar produciendo ningún resultado. Sin embargo, creo que este es el awnser. Me mantendré en ello. - edwardiglesias

Deberías hacer algo de depuración. print "@fields\n" dentro del bucle para ver lo que estás leyendo. ¿Has copiado el código exactamente? Sin el scalar el <$fh> comerá todos los datos y no dejará nada para el ciclo. - Borodin

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.