• Publicidad

Reemplazar espacios vacíos por NaN en una matriz

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

Reemplazar espacios vacíos por NaN en una matriz

Notapor CaroCaro » 2009-01-20 23:39 @027

¡¡ Ayuda por Favor !!

Hola,

Estoy aproblemada con unos datos y que quisiera modificar para poder trabajar con ellos. Éstos los descargo de un ftp y vienen con el siguiente formato:

(no pude disminuir el tamaño de la letra de la matriz... para apreciarla mejor hay que achicar la letra desde el explorador [CTRL -] con Firefox)

Código: Seleccionar todo
 2009001     53121   -8.0174    96.6855     0    21     29.56   12.19   11.63    5.60     4    1013.0     31.48   7.9     1.0   6.5   297.73             0.0
 2009001     53121   -8.0081    96.5554     0    21     30.20   12.39   12.04    5.63     4    1013.0     31.49   6.8     1.0   6.6   297.87             0.0
 2009001     53121   -7.9990    96.4257     0    21     29.52   12.03   11.73    5.63     4    1013.0     31.49   8.6     1.0   6.7   297.09             0.0
 2009001     53121   -7.9898    96.2963     0    21     29.53   12.01   11.66    5.71     4    1013.0     31.48   8.3     1.0   6.8   296.90             0.0
 2009001     53121   -7.9807    96.1673     0    21     29.25   11.62   11.40    6.10     4    1013.0     31.47   8.7     1.0   6.9   297.69             0.0
 2009001     53121   -7.9716    96.0386     0    21     29.49   11.61   11.65    6.13     4    1013.0     31.47   8.8     2.0   6.7   297.95     0.0     0.0
 2009001     53121   -7.9625    95.9103     0    21     27.38   11.06   10.62    5.59     4    1013.0     31.45  10.0     1.0   7.0   297.78             0.0
 2009001     53121   -7.9535    95.7822     0    21     29.73   12.30   12.17    5.14     4    1013.0     31.41   8.5     1.0   7.1   297.55             0.0
 2009001     53121   -7.9445    95.6545     0    21     30.20   12.73   12.57    4.76     4    1013.0     31.37   7.5     2.0   7.2   296.96     0.0     0.0
 2009001     53121   -7.9355    95.5272     0    21     30.76   12.57   12.68    5.38     4    1013.0     31.33   7.7     2.0   7.2   297.18     0.0     0.0
 2009001     53121   -7.9266    95.4001     0    21     30.11   12.19   12.34    5.48     4    1013.0     31.31   9.1     1.0   7.3   297.19             0.0
 2009001     53121   -7.9177    95.2734     0    21     29.97   11.43   11.78    6.68     4    1013.0     31.29   9.9     1.0   7.3   295.14             0.0
 2009001     53121   -7.9088    95.1470     0    21     31.84   12.44   13.14    6.17     4    1013.0     31.27   8.1     1.0   7.4   295.77             0.0
 2009001     53121   -7.9000    95.0209     0    21     30.42   11.75   12.15    6.44     4    1013.0     31.26   9.7     1.0   7.4   296.42             0.0
 2009001     53121   -7.8912    94.8951     0    21     31.28   12.00   12.56    6.64     4    1013.0     31.15   9.2     1.0   7.5   296.86             0.0
 2009001     53121   -7.8824    94.7696     0    21     31.63   12.50   13.01    6.04     4    1013.0     31.03   7.8     1.0   7.5   297.18             0.0
 2009001     53121   -7.8737    94.6444     0    21     30.06   11.54   11.83    6.62     4    1013.0     30.91   9.6     1.0   7.5   297.33             0.0
 2009001     53121   -7.8650    94.5196     1    25                                       4    1013.0
 2009001     53121   -7.8563    94.3950     1    25                                       4    1013.0
 2009001     53121   -7.8476    94.2707     1    25                                       4    1013.0
 2009001     53121   -7.8390    94.1467     0    21     30.23   12.15   12.09    5.90     4    1012.0     30.34   9.1     1.0   7.7   297.10     0.0     0.0
 2009001     53121   -7.8304    94.0230     1    25                                       4    1012.0
 2009001     53121   -7.8219    93.8996     1    25                                       4    1012.0
 2009001     53121   -7.8133    93.7765   999    23     37.85   13.09   17.68    7.00     4    1012.0     30.09
 2009001     53121   -7.8048    93.6537     1    25                                       4    1012.0


Descripción de la Matriz:
Es una matriz con 19 columnas de datos y literalmente miles de líneas...
Cualquiera de las columnas pueden traer datos vacíos y además el largo de los números puede variar pero siempre coinciden en la posición del último dígito.

Yo necesito colocar el string NaN donde hay espacios vacíos correspondientes a una columna, de modo que quede una Matriz Cuadrada, algo así:

Código: Seleccionar todo
 2009001     53121   -8.0174    96.6855     0    21     29.56   12.19   11.63    5.60     4    1013.0     31.48   7.9     1.0   6.5   297.73     NaN     0.0
 2009001     53121   -8.0081    96.5554     0    21     30.20   12.39   12.04    5.63     4    1013.0     31.49   6.8     1.0   6.6   297.87     NaN     0.0
 2009001     53121   -7.9990    96.4257     0    21     29.52   12.03   11.73    5.63     4    1013.0     31.49   8.6     1.0   6.7   297.09     NaN     0.0
 2009001     53121   -7.9898    96.2963     0    21     29.53   12.01   11.66    5.71     4    1013.0     31.48   8.3     1.0   6.8   296.90     NaN     0.0
 2009001     53121   -7.9807    96.1673     0    21     29.25   11.62   11.40    6.10     4    1013.0     31.47   8.7     1.0   6.9   297.69     NaN     0.0
 2009001     53121   -7.9716    96.0386     0    21     29.49   11.61   11.65    6.13     4    1013.0     31.47   8.8     2.0   6.7   297.95     0.0     0.0
 2009001     53121   -7.9625    95.9103     0    21     27.38   11.06   10.62    5.59     4    1013.0     31.45  10.0     1.0   7.0   297.78     NaN     0.0
 2009001     53121   -7.9535    95.7822     0    21     29.73   12.30   12.17    5.14     4    1013.0     31.41   8.5     1.0   7.1   297.55     NaN     0.0
 2009001     53121   -7.9445    95.6545     0    21     30.20   12.73   12.57    4.76     4    1013.0     31.37   7.5     2.0   7.2   296.96     0.0     0.0
 2009001     53121   -7.9355    95.5272     0    21     30.76   12.57   12.68    5.38     4    1013.0     31.33   7.7     2.0   7.2   297.18     0.0     0.0
 2009001     53121   -7.9266    95.4001     0    21     30.11   12.19   12.34    5.48     4    1013.0     31.31   9.1     1.0   7.3   297.19     NaN     0.0
 2009001     53121   -7.9177    95.2734     0    21     29.97   11.43   11.78    6.68     4    1013.0     31.29   9.9     1.0   7.3   295.14     NaN     0.0
 2009001     53121   -7.9088    95.1470     0    21     31.84   12.44   13.14    6.17     4    1013.0     31.27   8.1     1.0   7.4   295.77     NaN     0.0
 2009001     53121   -7.9000    95.0209     0    21     30.42   11.75   12.15    6.44     4    1013.0     31.26   9.7     1.0   7.4   296.42     NaN     0.0
 2009001     53121   -7.8912    94.8951     0    21     31.28   12.00   12.56    6.64     4    1013.0     31.15   9.2     1.0   7.5   296.86     NaN     0.0
 2009001     53121   -7.8824    94.7696     0    21     31.63   12.50   13.01    6.04     4    1013.0     31.03   7.8     1.0   7.5   297.18     NaN     0.0
 2009001     53121   -7.8737    94.6444     0    21     30.06   11.54   11.83    6.62     4    1013.0     30.91   9.6     1.0   7.5   297.33     NaN     0.0
 2009001     53121   -7.8650    94.5196     1    25       NaN     NaN     NaN     NaN     4    1013.0       NaN   NaN     NaN   NaN      NaN     NaN     NaN
 2009001     53121   -7.8563    94.3950     1    25       NaN     NaN     NaN     NaN     4    1013.0       NaN   NaN     NaN   NaN      NaN     NaN     NaN
 2009001     53121   -7.8476    94.2707     1    25       NaN     NaN     NaN     NaN     4    1013.0       NaN   NaN     NaN   NaN      NaN     NaN     NaN
 2009001     53121   -7.8390    94.1467     0    21     30.23   12.15   12.09    5.90     4    1012.0     30.34   9.1     1.0   7.7   297.10     0.0     0.0
 2009001     53121   -7.8304    94.0230     1    25       NaN     NaN     NaN     NaN     4    1012.0       NaN   NaN     NaN   NaN      NaN     NaN     NaN
 2009001     53121   -7.8219    93.8996     1    25       NaN     NaN     NaN     NaN     4    1012.0       NaN   NaN     NaN   NaN      NaN     NaN     NaN
 2009001     53121   -7.8133    93.7765   999    23     37.85   13.09   17.68    7.00     4    1012.0     30.09   NaN     NaN   NaN      NaN     NaN     NaN
 2009001     53121   -7.8048    93.6537     1    25       NaN     NaN     NaN     NaN     4    1012.0       NaN   NaN     NaN   NaN      NaN     NaN     NaN


He intentado diferentes cosas, pero ninguna funciona perfectamente:

Lo primero fue:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open(IN,"<dat.txt");
open(OUT,">datos.txt");

while($linea=<IN>){
chop($linea);
@datos=split(' ', $linea);
        for ($i=0;$i<=18;$i++)
        {
        $dc=$datos[$c];
                if(($dc==0) and ($dc!~0)){
                $dc=~s/$dc/NaN/g;
                } # End If
        } #end For
print OUT "@datos\n"

} #end While
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Esto no funcionó debido a que en la columna nº 7 reemplaza el espacio con el número 4, que pertenece a la columna n° 11.

Lo 2° fue ir carácter por carácter:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open(IN,"<dat.txt");
open(OUT,">datos.txt");

#Inicio del WHILE
while($linea=<IN>){
chop($linea);
@datos=split(//,$linea);

#Vector  para ir a la posición que corresponde a un dato
@pos=(7,17,27,38,44,50,60,68,76,84,90,100,110,116,124,130,139,147,155);

#       Inicio FOR
        for ($i=1;$i<=19;$i++)
        {
        $c=$pos[$i];
                if(($datos[$c]==0) and ($datos[$c]!~0)){
                $datos[$c]=~s/$datos[$c]/NaN/g;
                } # Fin del IF
        } # Fin del FOR

print OUT "@datos\n"
} #Fin del WHILE
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Pero no funcionó debido a que separa cada carácter con un espacio extra.

Código: Seleccionar todo
NaN 2 0 0 9 0 0 1           5 3 1 2 1       - 7 . 8 7 3 7         9 4 . 6 4 4 4           0         2 1           3 0 . 0 6       1 1 . 5 4       1 1 . 8 3         6 . 6 2           4         1 0 1 3 . 0           3 0 . 9 1       9 . 6           1 . 0       7 . 5       2 9 7 . 3 3               NaN           0 . 0
NaN 2 0 0 9 0 0 1           5 3 1 2 1       - 7 . 8 6 5 0         9 4 . 5 1 9 6           1         2 5                   NaN               NaN               NaN               NaN           4         1 0 1 3 . 0          NaN      NaN        NaN      NaN         NaN        NaN        NaN


:shock: ¡¡ Ayuda por Favor !! :(
CaroCaro
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2009-01-20 18:46 @823

Publicidad

Notapor explorer » 2009-01-21 04:39 @235

Bienvenido a los foros de Perl en Español, CaroCaro.

Esta es una manera, suponiendo que
a) las posiciones de las columnas no cambian
b) las líneas tienen espacios en blanco hasta el final de la última columna (todas las líneas tienen el mismo ancho).

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

# Vector para ir a la posición que corresponde a un dato
my @pos = (7,17,27,38,44,50,60,68,76,84,90,100,110,116,124,130,139,147,155);

open(IN, "<kk.txt" );
open(OUT,">kk1.txt");

#Inicio del WHILE
while (my $linea = <IN>) {
    for my $i (@pos) {
        if (substr($linea, $i-2, 3) eq '   ') {
            substr($linea, $i-2, 3) =  'NaN';
        }
    }

    print OUT $linea;
}

close OUT;
close IN;

__END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El truco está en que, como sabemos dónde termina cada columna, podemos hacer la sustitución de los 3 caracteres en blanco por 'NaN', en el caso de que esté en blanco esa columna.

Es también una buena oportunidad para ver en funcionamiento a substr() en el lado izquierdo de una asignación.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor CaroCaro » 2009-01-21 09:43 @446

¡¡¡¡¡Gracias por responder tan rápidamente!!!!! :D

Este script funciona casi perfecto... Debido a que algunas líneas que no tienen datos en las columnas finales tampoco poseen espacios en esas posiciones, es decir que dan un enter inmediatamente después del último dato registrado, por ese motivo faltan los últimos NaN en las filas que no tienen datos en las últimas columnas:

Código: Seleccionar todo
 2009001     53121   -7.8824    94.7696     0    21     31.63   12.50   13.01    6.04     4    1013.0     31.03   7.8     1.0   7.5   297.18     NaN     0.0
 2009001     53121   -7.8737    94.6444     0    21     30.06   11.54   11.83    6.62     4    1013.0     30.91   9.6     1.0   7.5   297.33     NaN     0.0
 2009001     53121   -7.8650    94.5196     1    25       NaN     NaN     NaN     NaN     4    1013.0
 2009001     53121   -7.8563    94.3950     1    25       NaN     NaN     NaN     NaN     4    1013.0
 2009001     53121   -7.8476    94.2707     1    25       NaN     NaN     NaN     NaN     4    1013.0
 2009001     53121   -7.8390    94.1467     0    21     30.23   12.15   12.09    5.90     4    1012.0     30.34   9.1     1.0   7.7   297.10     0.0     0.0
 2009001     53121   -7.8304    94.0230     1    25       NaN     NaN     NaN     NaN     4    1012.0
 2009001     53121   -7.8219    93.8996     1    25       NaN     NaN     NaN     NaN     4    1012.0
 2009001     53121   -7.8133    93.7765   999    23     37.85   13.09   17.68    7.00     4    1012.0     30.09
 2009001     53121   -7.8048    93.6537     1    25       NaN     NaN     NaN     NaN     4    1012.0

...


:? ¿Alguna idea?

Saludos
CaroCaro
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2009-01-20 18:46 @823

Notapor explorer » 2009-01-21 11:27 @519

Pues si faltan caracteres vacíos, los ponemos...

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

# Vector para ir a la posición que corresponde a un dato
my @pos = (7,17,27,38,44,50,60,68,76,84,90,100,110,116,124,130,139,147,155);
my $linea_largo = 156;
my $linea_vacia = ' ' x $linea_largo;

open(IN, "<kk.txt" );
open(OUT,">kk1.txt");

while (my $linea = <IN>) {
    chomp($linea);

    ## rellenamos por el final
    $linea = substr("$linea$linea_vacia", 0, $linea_largo);

    for my $i (@pos) {
        if (substr($linea,$i-2,3) eq '   ') {
            substr($linea,$i-2,3) =  'NaN';
        }
    }

    print OUT "$linea\n";
}

close OUT;
close IN;

__END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Lo que hacemos, aparte de lo anterior, es que a la $linea le sumamos un montón de espacios en blanco (de hecho, tantos como una línea entera, en blanco). Y la recortamos al largo que nos interesa.

Lo mismo se podría haber hecho con un sprintf(), aunque de una forma un poco más oscura, quizás:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
while (my $linea = <IN>) {
    chomp($linea);

    ## rellenamos por el final
    $linea = sprintf("%-*s\n", $linea_largo, $linea);

    for my $i (@pos) {
        if (substr($linea,$i-2,3) eq '   ') {
            substr($linea,$i-2,3) =  'NaN';
        }
    }

    print OUT $linea;
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Al sprintf() le pasamos un parámetro (*), que indica el largo del campo del string (s) que indicamos después. Y esa cadena de caracteres la colocamos alineada a la izquierda (-). Aprovechamos también para poner el retorno de carro que le quitamos con el chomp(), y que fue necesario hacer para poder agregar los caracteres en blanco.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor CaroCaro » 2009-01-21 12:55 @580

:D ¡¡¡¡¡ GRACIAS, FUNCIONA PERFECTO !!!!! :D
CaroCaro
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2009-01-20 18:46 @823


Volver a Básico

¿Quién está conectado?

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

cron