• Publicidad

Editar ficheros .dat en un solo .dat y por columnas

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

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor explorer » 2012-03-20 19:15 @844

Bueno, ya encontré una solución. Difiere en un paso, pero el resultado sale.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.10;
  3. use Data::CTable;
  4. use POSIX 'strftime';
  5.  
  6. # Leemos los ficheros
  7. my @archivos = <dir/*txt>;                      # Archivos a leer
  8.  
  9. my $tabla = Data::CTable->new;                  # Tabla
  10.  
  11. for my $i ( 1 .. @archivos ) {                  # Para todos los archivos
  12.  
  13.     my $col = Data::CTable->new;                # Creamos un objeto tabla, que tendrá solo una columna
  14.  
  15.     $col->read(                                 # Leemos
  16.         _FileName       => $archivos[$i-1],     # este archivo
  17.         _HeaderRow      => 0,                   # que no tienen cabeceras de campos
  18.         _FieldList      => [ $i ],              # porque las prefabricamos
  19.         _CacheOnRead    => 0,                   # y no queremos caché
  20.     );
  21.  
  22.     $col->row_delete(0);                        # Eliminamos la primera línea
  23.  
  24.     $tabla->combine( $col );                    # Combinamos la columna con la tabla
  25. }
  26.  
  27. for my $i ( 1 .. @archivos ) {                  # Volvemos a leer las columnas
  28.     my @indices = @{$tabla->all()};             # Índices de las filas
  29.     my $filas   = $tabla->col($i);              # Valores de las filas de la columna $i-ésima
  30.  
  31.     my $ancho_maximo = 0;                       # Calcularemos el ancho más grande
  32.  
  33.     for my $j (@indices) {                      # Para todos los índices de las filas de la columna,
  34.  
  35.         my $valor = $filas->[$j] // '';         # Leemos el valor de la celda
  36.  
  37.         my $ancho = length $valor;              # Sacamos el ancho de la fila $j-ésima
  38.  
  39.         if ($ancho_maximo < $ancho) {           # Si su ancho es aún más grande,
  40.             $ancho_maximo = $ancho;             # lo apuntamos
  41.         }
  42.     }                                           # ya sabemos el ancho máximo
  43.  
  44.     for my $j (@indices) {                      # Para todos los índices de las filas de la columna,
  45.         $filas->[$j]                            # Modificamos la fila $j-ésima
  46.             = sprintf "%*s", $ancho_maximo, $filas->[$j] // '';
  47.     }
  48. }                                               # Ya están modificados los valores de la tabla
  49.  
  50. my $largo = $tabla->length();
  51. #say "Largo: [$largo]";
  52.  
  53. # Agregamos la fecha
  54. $tabla->row_set($largo, { 1 => strftime '%Y%m%d%H', localtime});
  55. $tabla->row_move($largo, 0);
  56. #print @{$tabla->fieldlist()}, "\n";
  57.  
  58. # Escribimos la tabla
  59. $tabla->write(                                  # Escribimos
  60.     _FileName   => 'vientos.dat',               # este archivo
  61.     _HeaderRow  => 0,                           # sin cabeceras de campos
  62.     _FDelimiter => "\t",                        # y columnas separadas por tabuladores
  63. );
  64.  
  65. __END__
  66. 2012032101
  67.        1        a        A1
  68.       22        b        B2
  69.     3333        c        C3
  70.    -4.23        d        D4
  71. 55555.01        e        E5
  72.        6        f        F6
  73.    -7222                 G7
  74.      888                 H8
  75.        9                 I9
  76.                         J10
  77.                         K11
  78.                         L12
  79.                         M13
  80.                         N14
  81.                         O15
  82.                         P16
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4

El operador '//' (or-definido) es nuevo en Perl v5.10, así que por eso hay un 'use v5.10;' al principio.

La diferencia con la solución mía propuesta antes, es que no hace falta llamar a col_set(). Según la documentación, se puede acceder y cambiar los valores individuales de cada celda de la tabla de forma directa, lo cual es lo lógico si se trata de un módulo que nos permite manipular datos en forma de tabla.
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

Publicidad

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor enric73 » 2012-03-21 10:11 @466

Hola explorer,

Gracias, tendré que ponerme a fondo con el código, yo hice una chapuza y pasé de un dat de 40000 filas a uno de 16 millones de filas y la mayoría vacías...

Estaba utilizando estas comandas...
$tabla->col_get( $col );
$tabla->length( $col );
$col = sprintf("%.2f", $col);
$tabla->col_set( $col );

He ejecutado el script y me funciona sin errores de compilación, no he tenido que utilizar el cpan para instalar ningún módulo.

Esta tarde voy a escribir un poco de código para utilizar argumento de entrada, adjuntaré lo que hago, hasta luego, y muchas gracias, con esto del tratamiento de tablas iba muy perdido, pero veo que es muy práctico.

Una consulta, de paso, ¿con Perl hay funciones de interpolación gráfica?

Es decir, a partir de una serie de datos con sus coordenadas lat/lon u otras, poder interpolar sobre un gráfico en colores, ¿es posible de hacerlo con Perl? ¿O mejor que busque otro programa, como idl...?

Gracias.
enric73
Perlero nuevo
Perlero nuevo
 
Mensajes: 154
Registrado: 2012-03-16 06:27 @311

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor enric73 » 2012-03-21 12:57 @581

Hola Explorer,

Muchas gracias, unas preguntas... sobre el código en

-my @indices = @{$tabla->all()}; # Índices de las filas podria utilizar tambien $table->fieldlist_all()?
--my $ancho_maximo = 0; # Calcularemos el ancho más grande, partimos del valor 0?
--= sprintf "%*s", $ancho_maximo, $filas->[$j] // ''; Esta linea del formato exactamente que hace?

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. for my $i ( 1 .. @archivos ) {                  # Volvemos a leer las columnas
  2.     my @indices = @{$tabla->all()};             # Índices de las filas
  3.     my $filas   = $tabla->col($i);              # Valores de las filas de la columna $i-ésima
  4.  
  5.     my $ancho_maximo = 0;                       # Calcularemos el ancho más grande
  6.  
  7.     for my $j (@indices) {                      # Para todos los índices de las filas de la columna,
  8.  
  9.         my $valor = $filas->[$j] // '';         # Leemos el valor de la celda
  10.  
  11.         my $ancho = length $valor;              # Sacamos el ancho de la fila $j-ésima
  12.  
  13.         if ($ancho_maximo < $ancho) {           # Si su ancho es aún más grande,
  14.             $ancho_maximo = $ancho;             # lo apuntamos
  15.         }
  16.     }                                           # ya sabemos el ancho máximo
  17.  
  18.     for my $j (@indices) {                      # Para todos los índices de las filas de la columna,
  19.         $filas->[$j]                            # Modificamos la fila $j-ésima
  20.             = sprintf "%*s", $ancho_maximo, $filas->[$j] // '';
  21.     }
  22. }                                               # Ya están modificado
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


-Otra consulta, me he dado cuenta que algunas cifras solamente tienen un decimal o zero, y quiero tenerlos todos con dos decimales, puedo utilizar $rounded = sprintf("%.2f", $number);? es decir $filas->[$j] # Modificamos la fila $j-ésima
= sprintf "%.2f", $filas->[$j] // ''?


Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
  4.82    2.75     1.1    0.04   -4.06   -4.45   -4.68   -5.25   -5.82   -5.98   -0.35   -6.25
  4.91    2.85    1.23    0.16   -4.02   -4.41   -4.65   -5.23   -5.81   -5.98   -0.24   -6.24
  4.99    2.94    1.35    0.28   -3.97   -4.37   -4.62   -5.21   -5.79   -5.97   -0.13   -6.23
  5.07    3.04    1.48     0.4   -3.93   -4.33   -4.58   -5.18   -5.78   -5.96   -0.02   -6.22
  5.14    3.14     1.6    0.52   -3.88   -4.28   -4.54   -5.15   -5.76   -5.94    0.09   -6.21
  5.22    3.23    1.72    0.64   -3.83   -4.24   -4.51   -5.13   -5.74   -5.93     0.2   -6.19
   5.3    3.33    1.85    0.76   -3.78    -4.2   -4.47    -5.1   -5.71   -5.91     0.3   -6.17
  5.37    3.42    1.97    0.88   -3.73   -4.15   -4.43   -5.06   -5.69   -5.89    0.41   -6.15
  5.44    3.51    2.09       1   -3.67    -4.1   -4.38   -5.03   -5.66   -5.87    0.52   -6.13
  5.51    3.61    2.21    1.12   -3.62   -4.05   -4.34      -5   -5.63   -5.85    0.63   -6.11
  5.58     3.7    2.33    1.24   -3.56      -4    -4.3   -4.96    -5.6   -5.83    0.74   -6.08
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4



Buenas tardes, y gracias.
enric73
Perlero nuevo
Perlero nuevo
 
Mensajes: 154
Registrado: 2012-03-16 06:27 @311

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor explorer » 2012-03-21 17:06 @754

enric73 escribiste:Una consulta, de paso, ¿con Perl hay funciones de interpolación gráfica?

Es decir, a partir de una serie de datos con sus coordenadas lat/lon u otras, poder interpolar sobre un gráfico en colores, ¿es posible de hacerlo con Perl? ¿O mejor que busque otro programa, como idl...?

En tiempos, de forma profesional, yo usaba PDL::Transform::Cartography y Geo::Proj4, con lo que no había problemas en interpolar posiciones en mapas, en múltiples proyecciones.

En CPAN hay algunos más.

La curva de aprendizaje es altísima (más bien es una escalada), pero la ventaja es que una vez puesto en marcha puedes automatizar muchas tareas de procesamiento de datos sin depender del IDL, que creo que, además, es propietario.
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

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor explorer » 2012-03-21 17:33 @773

enric73 escribiste:unas preguntas... sobre el código en

-my @indices = @{$tabla->all()}; # Índices de las filas podría utilizar también $table->fieldlist_all()?
No. all() devuelve los índices para acceder a las filas, mientras que fieldlist_all devuelve los nombres de las columnas.

enric73 escribiste:--my $ancho_maximo = 0; # Calcularemos el ancho más grande, ¿partimos del valor 0?
Sí.

enric73 escribiste:--= sprintf "%*s", $ancho_maximo, $filas->[$j] // ''; Esta linea del formato exactamente ¿qué hace?
$filas->[$j] nos devuelve el valor $j-ésimo de la fila $filas.
sprintf() nos formatea ese valor según lo que dice la cadena de formato "%*s".
La cadena de formato quiere decir: «coge el siguiente argumento de los que se han pasado a sprintf() y ponlo en lugar del '*'. Como ese argumento es $ancho_maximo, lo que estamos haciendo es definiendo el ancho de una cadena de texto. Ejemplo: si ese ancho es 6, la cadena de formato queda "%6s" que quiere decir que en la salida sprintf() debe generar una cadena de caracteres de 6 posiciones, y meter dentro de ella el siguiente argumento, que es el valor de la fila. De esta manera, el valor queda "metido" dentro de un espacio más grande, y ajustado a la derecha. O sea, como queremos que quede.

enric73 escribiste:-Otra consulta, me he dado cuenta que algunas cifras solamente tienen un decimal o cero, y quiero tenerlos todos con dos decimales, ¿puedo utilizar $rounded = sprintf("%.2f", $number);? es decir $filas->[$j] # Modificamos la fila $j-ésima
= sprintf "%.2f", $filas->[$j] // ''?
Sí, claro. Pero debes indicar además el ancho máximo calculado antes, para que lo haga todo en un solo paso.
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

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor enric73 » 2012-03-21 17:38 @776

Muchas gracias por la ayuda y explicaciones explorer. Buenas noches.
enric73
Perlero nuevo
Perlero nuevo
 
Mensajes: 154
Registrado: 2012-03-16 06:27 @311

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor enric73 » 2012-03-23 04:18 @221

Hola explorer, he introducido dos lineas en el script para que todos los valores tengan dos decimales, me ha salido. Puedes mirar las dos lineas para saber si es la mejor manera de hacerlo? muchas gracias

#!/usr/bin/env perl
use v5.10;
use Data::CTable;
use POSIX 'strftime';

# Leemos los ficheros
my @archivos = <dir/*txt>; # Archivos a leer

my $tabla = Data::CTable->new; # Tabla

for my $i ( 1 .. @archivos ) { # Para todos los archivos

my $col = Data::CTable->new; # Creamos un objeto tabla, que tendrá solo una columna

$col->read( # Leemos
_FileName => $archivos[$i-1], # este archivo
_HeaderRow => 0, # que no tienen cabeceras de campos
_FieldList => [ $i ], # porque las prefabricamos
_CacheOnRead => 0, # y no queremos caché
);

$col->row_delete(0); # Eliminamos la primera línea

$tabla->combine( $col ); # Combinamos la columna con la tabla
}

for my $i ( 1 .. @archivos ) { # Volvemos a leer las columnas
my @indices = @{$tabla->all()}; # Índices de las filas
my $filas = $tabla->col($i); # Valores de las filas de la columna $i-ésima

my $ancho_maximo = 0; # Calcularemos el ancho más grande

for my $j (@indices) { # Para todos los índices de las filas de la columna,

my $valor = $filas->[$j] // ''; # Leemos el valor de la celda
$files->[$j]
= sprintf "%.2f", $valor, $files->[$j] // '';

my $ancho = length $valor; # Sacamos el ancho de la fila $j-ésima

if ($ancho_maximo < $ancho) { # Si su ancho es aún más grande,
$ancho_maximo = $ancho; # lo apuntamos
}
} # ya sabemos el ancho máximo

for my $j (@indices) { # Para todos los índices de las filas de la columna,
$filas->[$j] # Modificamos la fila $j-ésima
= sprintf "%*s", $ancho_maximo, $filas->[$j] // '';
}
} # Ya están modificados los valores de la tabla

my $largo = $tabla->length();
#say "Largo: [$largo]";

# Agregamos la fecha
$tabla->row_set($largo, { 1 => strftime '%Y%m%d%H', localtime});
$tabla->row_move($largo, 0);
#print @{$tabla->fieldlist()}, "\n";

# Escribimos la tabla
$tabla->write( # Escribimos
_FileName => 'vientos.dat', # este archivo
_HeaderRow => 0, # sin cabeceras de campos
_FDelimiter => "\t", # y columnas separadas por tabuladores
);



En azul está el codigo introducido,
antes en alguna dato tenia un decimal o ninguno
4.17 3.03 3.49 3.86 2.7 3.18 3.52 3.85
4.22 3.09 3.56 3.93 2.76 3.25 3.58 3.92
4.27 3.15 3.62 4 2.82 3.31 3.64 3.99
4.31 3.2 3.69 4.06 2.88 3.38 3.71 4.05
4.36 3.26 3.75 4.12 2.94 3.44 3.77 4.12
4.4 3.31 3.81 4.18 3 3.5 3.83 4.18
4.45 3.37 3.87 4.25 3.05 3.56 3.88 4.24
4.49 3.42 3.93 4.3 3.11 3.62 3.94 4.3
4.53 3.47 3.99 4.36 3.16 3.68 4 4.36
4.56 3.53 4.05 4.42 3.22 3.74 4.05 4.42
4.6 3.58 4.1 4.48 3.27 3.79 4.11 4.47
y ahora dos decimales en todos
4.17 3.03 3.49 3.86 2.70 3.18 3.52 3.85
4.22 3.09 3.56 3.93 2.76 3.25 3.58 3.92
4.27 3.15 3.62 4.00 2.82 3.31 3.64 3.99
4.31 3.20 3.69 4.06 2.88 3.38 3.71 4.05
4.36 3.26 3.75 4.12 2.94 3.44 3.77 4.12
4.40 3.31 3.81 4.18 3.00 3.50 3.83 4.18
4.45 3.37 3.87 4.25 3.05 3.56 3.88 4.24
4.49 3.42 3.93 4.30 3.11 3.62 3.94 4.30
4.53 3.47 3.99 4.36 3.16 3.68 4.00 4.36
4.56 3.53 4.05 4.42 3.22 3.74 4.05 4.42
4.60 3.58 4.10 4.48 3.27 3.79 4.11 4.47
enric73
Perlero nuevo
Perlero nuevo
 
Mensajes: 154
Registrado: 2012-03-16 06:27 @311

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor explorer » 2012-03-23 07:47 @366

No, no hace falta eso. Te dije que lo podías hacer todo en una sola pasada:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.             = sprintf "%*.2f", $ancho_maximo, $filas->[$j] // 0;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El parámetro $ancho_máximo lo metemos como primera parte de %f; luego sigue la precisión (dos decimales), y luego, al final, donde está el dato que queremos, $filas->[$j], le ponemos un '// 0' para el caso de que si no está definido, pongamos un valor 0 por defecto.
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

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor enric73 » 2012-03-27 05:00 @250

Buenos días, explorer

¡Tengo una consulta para hacerte!

En el programa, ahora puede tratar archivos que empiezan por UGRD10*.dat, pero también necesito abrir archivos VGRD10*.dat y ordenarlos por horas de forma alternativa (la hora está en el final de cada fichero: _hh.dat). Por ejemplo, UGRD10_00.dat, VGRD10_00.dat, UGRD10_03.dat, VGRD10_03.dat.

He de añadir my @archivos2 = </home/enric/ASCII/VGRD10m*.dat>; pero para que aparezcan las columnas alternadas, una de la componente U del viento y otra de la componente V del viento para una cierta hora (timestep), ¿cuál es la manera de hacerlo utilizando este script? ¿He de duplicar la tabla, hacer una my $tabla2?

¡Muchas gracias y buenos días!
-------------------------------------------------------------------------
#!/usr/bin/env perl
use v5.10;
use Data::CTable;
use POSIX 'strftime';

# Leemos los ficheros
my @archivos = </home/enric/ASCII/UGRD10m*.dat>; # Archivos a leer

my $tabla = Data::CTable->new; # Tabla

for my $i ( 1 .. @archivos ) { # Para todos los archivos

my $col = Data::CTable->new; # Creamos un objeto tabla, que tendrá solo una columna

$col->read( # Leemos
_FileName => $archivos[$i-1], # este archivo
_HeaderRow => 0, # que no tienen cabeceras de campos
_FieldList => [ $i ], # porque las prefabricamos
_CacheOnRead => 0, # y no queremos caché
);

$col->row_delete(0); # Eliminamos la primera línea

$tabla->combine( $col ); # Combinamos la columna con la tabla
}

for my $i ( 1 .. @archivos ) { # Volvemos a leer las columnas
my @indices = @{$tabla->all()}; # Índices de las filas
my $filas = $tabla->col($i); # Valores de las filas de la columna $i-ésima

my $ancho_maximo = 0; # Calcularemos el ancho más grande

for my $j (@indices) { # Para todos los índices de las filas de la columna,

my $valor = $filas->[$j] // ''; # Leemos el valor de la celda

my $ancho = length $valor; # Sacamos el ancho de la fila $j-ésima

if ($ancho_maximo < $ancho) { # Si su ancho es aún más grande,
$ancho_maximo = $ancho; # lo apuntamos
}
} # ya sabemos el ancho máximo

for my $j (@indices) { # Para todos los índices de las filas de la columna,
$filas->[$j] # Modificamos la fila $j-ésima
= sprintf "%*s", $ancho_maximo, $filas->[$j] // '';
}
} # Ya están modificados los valores de la tabla

my $largo = $tabla->length();
#say "Largo: [$largo]";

# Agregamos la fecha
$tabla->row_set($largo, { 1 => strftime '%Y%m%d%H', localtime});
$tabla->row_move($largo, 0);
#print @{$tabla->fieldlist()}, "\n";

# Escribimos la tabla
$tabla->write( # Escribimos
_FileName => 'vientos.dat', # este archivo
_HeaderRow => 0, # sin cabeceras de campos
_FDelimiter => "\t", # y columnas separadas por tabuladores
);
enric73
Perlero nuevo
Perlero nuevo
 
Mensajes: 154
Registrado: 2012-03-16 06:27 @311

Re: Editar ficheros .dat en un solo .dat y por columnas

Notapor explorer » 2012-03-27 15:35 @691

¿Como que para una determinada hora?

¿Quieres decir que debes meter en el programa la hora que quieres procesar?

¿O quieres leer todos los archivos, ordenarlos por hora, e intercalar los archivos 'U' y 'V'?

Y también, ¿eso quiere decir que la tabla solo tendrá dos columnas, la 'U' y la 'V'?
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

AnteriorSiguiente

Volver a Básico

¿Quién está conectado?

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