• Publicidad

Trabajando con solo una región de muchas tablas

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Trabajando con solo una región de muchas tablas

Notapor andrea » 2007-07-27 16:49 @742

Hola a todos...

Estoy hace demasiados días tratando de hacer mi script y no pasa nada... de hecho ya estoy empezando a estresarme :( .

Este es el asunto, requiero sacar promedio y desviación estándar de solo una parte de una matriz de números. El segundo asunto es que requiero hacer esto para muchas, muchas matrices... y agrupar los valores obtenidos en alguna tabla. Solo necesito que la región que tengo que analizar sea una variable. Todas las matrices tienen la misma extensión, así que podría trabajar con todas ellas a la vez...

Me estoy volviendo loca con esto... ¡¡¡Please, ayuda!!! :cry:
andrea
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2007-07-27 16:29 @728

Publicidad

Notapor explorer » 2007-07-27 20:09 @881

Bienvenida a los foros de Perl en Español, Andrea.

Pero, ¿de cuántos datos estamos hablando? Si son pocos se pueden calcular con Perl, pero si son millones, mejor hacerlos con PDL.

¿Cuántas dimensiones tienen esas matrices?

¿Has escrito algo de código?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Lo que llevo hasta ahora

Notapor andrea » 2007-07-30 11:01 @500

¡Hola! ¡Gracias por contestar!
Mira: esto es lo que llevo... lo hice pensando solo en una matriz... son alrededor de 150 matrices de 115x115... En mis momentos de colapso empecé a hacerlo con Excel y ni siquiera coincidieron los resultados con mi script :(

Muchas gracias por ayudarme...

Andrea

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
print "\nIngrese nombre del file :";
$filename=<STDIN>;
chomp $filename;
unless(open (FILE,$filename)){ print "\n\nNo encuentro el archivo\n";}
#open (FILE2,">1.mt");
@Fld=<FILE>;
close FILE;
print "ingrese region:"; #Aca se deberia ingresar la region a calcular, semejante a excel, ej. B4:DL20
$column=<STDIN>;
print " - ";
$end=<STDIN>;
chomp $end;

my $sum = 0;
my $N = 10;
my $column = 1;
my $C = $column - 1;
my $ssum = 0;

    if (/^[^#]/) {
        $_ =~ s/^\s+//;


        my @Fld = split(/\s+/, $_, 9999);
print "@Kld";
        next if ( $#Fld< $C );
        my $x = ( $Fld[$C] );
        $sum += $x;
        $ssum += $x*$x;
        $N += 1;
    }

my $av = $sum/$N;

my $var = $ssum/($N-1) - $N * $av * $av/($N-1);

my $stddev = sqrt($var);
print  "Points:   $N\n";
print  "Mean:     $av\n";
print  "Variance: $var\n";
print  "Stddev:   $stddev\n";
print  "Sum:      $sum\n";

exit;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
andrea
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2007-07-27 16:29 @728

Notapor explorer » 2007-07-30 12:55 @579

Hay varios errores:

* es recomendable empezar siempre con las líneas
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use strict;
use warnings;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
para que Perl nos ayude a detectar problemas en el código
* lees todas las líneas del fichero de datos con <FILE> pero unas líneas más abajo pierdes el contenido al asignarle el resultado del split de $_, que no sabemos en todo el programa qué valor tiene
* en el cálculo de la suma, siempre estás sumando las misma columna C
* no haces un bucle por las filas de la región

Dentro de un rato te mando una solución...
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor andrea » 2007-07-30 13:18 @595

:oops:

Tienes toda la razón (me mareo entre tanto código)... estaría muy agradecida si me ayudas con esto...
¡gracias!

Andrea
andrea
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2007-07-27 16:29 @728

Notapor explorer » 2007-07-30 15:15 @677

Esta es una primera solución.

Es capaz de procesar todos los ficheros que le indiques en la línea de órdenes. Por ejemplo:

Código: Seleccionar todo
estadisticas.pl AA34:BC12 fichero1.txt fichero2.txt
Como ves, da igual que el rango esté desordenado (34>12).

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;

# Primero, unas inicializaciones
# Las letras son 26, desde la 'A' a la 'Z'
my @letras = ('A' .. 'Z');
@letras == 26 or die "ERROR de la aplicación: no hay 26 letras de la 'A' a la 'Z'\n";

# Transformación de letras a números en base 1: A=1, B=2, etc.
my %letras = map { $letras[$_] => $_+1 } 0 .. $#letras;

# Tamaño máximo de la matriz
my $maxima_dimension = 115;

# Cómo se usa este programa
sub uso {
    print <<USO;
Uso: $0 <rango al estilo Excel> fichero [fichero [...]]
El rango debe ser del tipo <columna><fila>:<columna><fila>

USO

}

#################
# Leemos el rango
my $rango = shift @ARGV;
if ( !$rango ) {
    uso();
    die "ERROR: No me has indicado el rango\n";
}

# Interpretamos el rango para convertilo a números
my @esquinas = split q{:}, $rango;
if ( @esquinas != 2 ) {
    uso();
    die "ERROR: el rango no está bien formado\n";
}

# Convertimos una esquina a un número de columna y fila
# en base (0,0): la esquina superior izquierda será la (0,0)
sub esquina_a_numero {
    my $esquina = shift;

    $esquina = uc $esquina;  # Lo pasamos a mayúsculas
                             # por si acaso

    # La esquina se compone de unas letras (columna)
    # y un número (fila)
    my ($columna,$fila) = $esquina =~ /([A-Z]+)([0-9]+)/;
    if ( !$columna or !$fila ) {
        uso();
        die "ERROR: el rango no está bien formado\n";
    }

    # Convertimos la columna, de letra a número
    # Recorremos la $columna, cada letra, y vamos pasando
    # a número
    my $numero = 0;
    foreach my $letra ( split q{}, $columna ) {
        # Aunque somos de letras, hay que echar números
        $numero = $numero * @letras + $letras{$letra};
    }
    $columna = $numero;

    # ¿Estamos dentro del rango?
    if ( $columna < 1 or $columna > $maxima_dimension ) {
        die "ERROR: la columna ($columna) es superior al ancho máximo\n";
    }

    # ¿Y la fila?
    if ( $fila < 1 or $fila > $maxima_dimension ) {
        die "ERROR: la fila ($fila) es superior al alto máximo\n";
    }

    # Devolvemos los valores, en base 0
    return $columna-1, $fila-1;
}

# Ahora sí, convertimos las dos esquinas a posiciones X e Y
my ($x1, $y1) = esquina_a_numero($esquinas[0]);
my ($x2, $y2) = esquina_a_numero($esquinas[1]);

# Tenemos que ordenar las posiciones para que vayan de
# izquierda a derecha
if ( $x1 > $x2 ) {
    ($x1, $x2) = ($x2, $x1);
}
# y de arriba a abajo
if ( $y1 > $y2 ) {
    ($y1, $y2) = ($y2, $y1);
}

# Informamos
print "Procesamos ficheros en el rango ($x1,$y1)x($x2,$y2)\n";


###############################
# Procesamiento de los ficheros
@ARGV or die "ERROR: no hay ficheros que procesar";

# Por cada fichero
foreach my $fichero ( @ARGV ) {

    print "$fichero\n";

    # Nos leemos el fichero a memoria
    my @lineas = do {
        open FH,"<$fichero" or die "ERROR: No puedo leer fichero $fichero: $!\n";
        <FH>;
    };

    # Comprobamos la altura de la tabla leída
    if ( @lineas < $maxima_dimension ) {
        die "ERROR: Hay menos líneas que la altura esperada: $maxima_dimension\n";
    }

    # Creamos la tabla
    my @tabla;
    foreach my $linea ( @lineas ) {

        my @columnas = split q{ }, $linea;
        if ( @columnas < $maxima_dimension ) {
            die "ERROR: Hay menos columnas que el ancho esperado: $maxima_dimension\n";
        }

        # Vamos creando una lista de listas de elementos
        push @tabla, [ @columnas ];
    }

    # Estadísticas
    my $suma  = 0;
    my $suma2 = 0;
    my $N     = 0;
    my $x;
    for (my $i = $x1; $i <= $x2; $i++) {
    for (my $j = $y1; $j <= $y2; $j++) {

        $N++;

        $x = $tabla[$j][$i];   # Es muy sencillo el acceso,
                               # gracias a la forma de guardar los datos,
                               # anteriormente

        $suma  += $x;
        $suma2 += $x * $x;
    }
    }

    my $media      = $suma / $N;
    my $varianza   = ($suma2 - $N * $media * $media) / ($N - 1);
    my $desviacion = sqrt( $varianza );

    print "\tPuntos  : $N\n";
    print "\tSuma    : $suma\n";
    print "\tMedia   : $media\n";
    print "\tVarianza: $varianza\n";
    print "\tDesviac.: $desviacion\n";
    print "\n";
}
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
Lo he verificado con un fichero de prueba y con OpenOffice Calc.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Funciona!!!! =D

Notapor andrea » 2007-07-30 17:30 @771

¡Este foro es lo mejor que he encontrado en mucho tiempo!
Tu script funciona excelente con mis archivos.
Miles de gracias por solucionar mi drama de semanas...

Andrea :D
andrea
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2007-07-27 16:29 @728

Notapor explorer » 2007-07-30 17:43 @780

Ahora, Andrea, piensa:

¿Te imaginas el tiempo que ahorrarás en el futuro cuando sepas Perl?

El trabajo de dos semanas, hecho en dos horas. Y sólo la primera vez.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor andrea » 2007-07-30 17:55 @788

Uuuffff... ¡ni me digas! Ahora mismo estoy viendo algún libro de Perl que me pueda servir para comprarlo... yo creo que con el libro y tu ayuda haré mi vida mucho más fácil :lol:

Gracias por todo :D
andrea
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2007-07-27 16:29 @728


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados