• Publicidad

Eliminar datos redundantes de una tabla

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Eliminar datos redundantes de una tabla

Notapor Alfumao » 2016-03-16 04:05 @211

Buenos días.

Aquí sigo con tablas y problemas derivados. Necesito "filtrar" una tabla (texto separado por tabuladores) con miles de filas y decenas de columnas en la que todos los valores de la columna 1 pueden aparecer repetidos en varias filas, y la intención es eliminar esas filas donde se produzca la repetición.

Había pensado en una estructura tipo Hash of Arrays, en la que si la primera columna actúa como referencia para el filtrado. Así, el valor de la primera columna se va introduciendo como clave y luego se busca en los arrays (valores del hash) de las siguientes líneas, y si se encuentra, se elimina esa línea.

Ejemplo reducido de tabla:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
A_clavatus_280  A_clavatus_280  A_flavus_132    None    None    T_verrucosum_99
A_flavus_413    A_clavatus_280  A_flavus_413    None    None    T_verrucosum_99
C_dubliniensis_121      None    None    C_dubliniensis_121      S_schenckii_304 None
C_dubliniensis_11       None    None    C_dubliniensis_121      S_schenckii_304 None
S_schenckii_70  A_clavatus_20   A_flavus_132    None    S_schenckii_70  T_verrucosum_110
T_verrucosum_14 A_clavatus_251  A_flavus_108    None    S_schenckii_228 T_verrucosum_14
C_dubliniensis_111      None    None    C_dubliniensis_121      None    None
 
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


No puedo poner un código de muestra, porque como todos me funcionan tan rematadamente mal, prefiero no interferir con un programa que no sirve...
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Publicidad

Re: Eliminar datos redundantes de una tabla

Notapor explorer » 2016-03-16 10:20 @472

Con un solo hash te vale.

Lees cada línea.
Extraes la primera columna.
Si ya existe $hash{$columna1}, entonces es que ya viste esa fila, así que saltas a leer la siguiente.
Si no existe, guardas la fila (en un archivo, en un array), y pones $hash{$columna1} = 1;
Repetir para todas las filas.
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: Eliminar datos redundantes de una tabla

Notapor Alfumao » 2016-03-16 12:01 @542

¿Algo como esto? No lo he podido probar aún, pero creo que con esto solo comprobaría si se repite la clave en la primera columna, y lo que buscamos es que la clave no se repita ni en la primera columna ni en ninguna posición de la fila... no sé si me explico.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5. use Getopt::Long;
  6. use Data::Dumper;
  7.  
  8. #usage:perl TableHoA.pl -p /path_to_table/
  9.  
  10.  
  11. my ($path);
  12. GetOptions(
  13.           'path=s'           => \$path,
  14.         );
  15.  
  16. chdir $path or die "ERROR: Unable to enter $path: $!\n";
  17. opendir (TEMP , ".") || die "ERROR: Unable to open dir: $!\n";
  18. my @nombres = readdir (TEMP);
  19. closedir TEMP;
  20. my %HoA=();
  21. my@TM=();#array para almacenar los datos obtenidos
  22. open  OUT,'>'."tabla_filtrada.tsv" or die "ERROR: $!\n";#archivo para imprimir los datos obtenidos
  23.  
  24.  
  25. #Lees cada línea.
  26. for $_ (@nombres) {
  27.  
  28.        if (/(\w+\.tab)$/){# salta si no es una extensión que buscamos
  29.               $target=$1;
  30.               print"Table:$target\n";
  31.              
  32.               open (INFILE, "$target") || die ("can´t open input file");
  33.               chomp(my @data = <INFILE>);
  34.              
  35.               #Repetir para todas las filas.
  36.               for my $line(@data){
  37.                 #Extraes la primera columna.
  38.                 my($columna1,@resto)== split(/\t/, $_);
  39.                 $HoA{$columna1}=@resto;
  40.                 #push(@{$HoA{$key}},$col1 );
  41.                 #Si ya existe $hash{$columna1}, entonces es que ya viste esa fila, así que saltas a leer la siguiente.
  42.                 if (exists $HoA{$columna1}){
  43.                     next;
  44.                 #Si no existe, guardas la fila (en un archivo, en un array), y pones $hash{$columna1} = 1;    
  45.                 }else{
  46.                    
  47.                     $HoA{$columna1} = 1;
  48.                     push @TM,"$line\n";
  49.                     print OUT"$line\n";
  50.                 }
  51.             }
  52.         }
  53.     }      
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


Ya me dirás si lo he hecho muy mal... Y qué me sugieres.

;)
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Eliminar datos redundantes de una tabla

Notapor explorer » 2016-03-16 18:00 @792

Humm... interesante...

Yo lo que haría sería ir agregando las claves de las primeras columnas a una exp. reg., para hacerla coincidir con la siguiente línea. Si hay coincidencia, pues saltamos a la siguiente, y si no, agregamos la primera columna, y repetimos.

A ver si mañana tengo un rato...
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: Eliminar datos redundantes de una tabla

Notapor Alfumao » 2016-03-17 03:17 @179

¿Te refieres a algo como esto?
(Pongo unicamente el fragmento referido a mi interpretacion de tu propuesta en forma de subrutina que es como lo pretendo utilizar).

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub hoa_table{
  2.        
  3.     my($target,$HoA)=@_;#paso el hash como referencia a la subrutina-> &hoa_table($target,\%HoA);
  4.  
  5.     print"HoA file $target\n";
  6.     my($name,$exte)= split(/\./, $target);
  7.  
  8.     open  SALIDA,'>'."$name.tsv" or die "ERROR: $!\n";
  9.  
  10.     my@arrkeys= keys %HoA;#creo array con las claves del hash ¿esta bien de-referenciar el hash asi?
  11.  
  12.        foreach my $ak (@arrkeys){
  13.            
  14.             my@arrline=@{$HoA{$ak}};#extraigo el array relacionado con la clave
  15.             my @sorted_arrline = sort @arrline;#lo ordeno (esto es por conveniencia personal)
  16.             my $sorted_print=join "\t",@sorted_arrline;#genero un string para buscar en el
  17.                        
  18.              unless($sorted_print=~/$ak/){
  19.                 print SALIDA "$ak\t "; #imprimo la clave en el fichero de salida
  20.                 print SALIDA"$sorted_print\n";#si no aparece la clave,imprimo el array en el fichero de salida
  21.                 }
  22.             }
  23. }
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4
Última edición por Alfumao el 2016-03-17 04:07 @213, editado 1 vez en total
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Eliminar datos redundantes de una tabla

Notapor explorer » 2016-03-17 03:44 @197

Esta es una posible solución:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use autodie;
  3.  
  4. open my $ENTRADA, '<', 'code_39344.txt';
  5. open my $SALIDA,  '>', 'salida.txt';
  6.  
  7.  
  8. my $linea = <$ENTRADA>;                 # leemos la primera línea
  9. my($columna1) = split " ", $linea, 2;
  10. my $ya_vista = $columna1;
  11.  
  12. print $SALIDA $linea;                           # sacamos la primera línea
  13.  
  14.  
  15. while (my $linea = <$ENTRADA>) {                # para el resto de líneas
  16.  
  17.     next if $linea =~ /$ya_vista/;              # saltamos a la siguiente si $ya_vista
  18.  
  19.     my($columna1) = split " ", $linea, 2;       # no, entonces sacamos la primera columna
  20.  
  21.     $ya_vista .= "|$columna1";                  # y la agregamos como opción al
  22.  
  23.     print $SALIDA $linea;
  24. }
  25.  
  26. close $ENTRADA;
  27. close $SALIDA;
  28.  
  29. __END__
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Dado el archivo indicado antes, la salida ahora es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
A_clavatus_280  A_clavatus_280  A_flavus_132    None    None    T_verrucosum_99
C_dubliniensis_121      None    None    C_dubliniensis_121      S_schenckii_304 None
S_schenckii_70  A_clavatus_20   A_flavus_132    None    S_schenckii_70  T_verrucosum_110
T_verrucosum_14 A_clavatus_251  A_flavus_108    None    S_schenckii_228 T_verrucosum_14
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
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: Eliminar datos redundantes de una tabla

Notapor Alfumao » 2016-03-17 04:30 @229

Hola, explorer.

El programa que planteas funciona con el ejemplo, pero en este caso:

- Tenemos miles de filas que recorrer
- Cada "$ya_vista" se puede encontrar en cualquiera de ellas
- Necesitamos que los miles de identificadores presentes en la columna 1 se revisen secuencialmente para seleccionar solo las filas sin repeticiones de los valores de la columna 1
- Además la primera vez que aparece dicho identificador en la columna 1, hace que este no pueda volver a aparecer en las siguientes líneas inspeccionadas
- Esto me hace pensar que hay que almacenar las líneas seleccionadas en algún tipo de array que una vez hecho todo el rastreo, podamos imprimir, ya que si imprimimos una línea cada vez, no sé si íbamos a filtrar la tabla correctamente...

¿Qué opinas?
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Eliminar datos redundantes de una tabla

Notapor explorer » 2016-03-18 04:18 @220

Alfumao escribiste:- Tenemos miles de filas que recorrer
- Cada "$ya_vista" se puede encontrar en cualquiera de ellas
- Necesitamos que los miles de identificadores presentes en la columna 1 se revisen secuencialmente para seleccionar solo las filas sin repeticiones de los valores de la columna 1
- Además la primera vez que aparece dicho identificador en la columna 1, hace que este no pueda volver a aparecer en las siguientes líneas inspeccionadas
- Esto me hace pensar que hay que almacenar las líneas seleccionadas en algún tipo de array que una vez hecho todo el rastreo, podamos imprimir, ya que si imprimimos una línea cada vez, no sé si íbamos a filtrar la tabla correctamente...

A ver... te explico mi solución, a ver si así se ajusta a lo que pedías.

Voy leyendo línea por línea, extrayendo la primera columna, y agregando ese campo al patrón $ya_vista.

Esto tiene el siguiente efecto (adecuando las respuesta a tus cuestiones):
- El archivo se lee una sola vez, así que no importa su tamaño
- Los identificadores se leen una vez y se buscan en cada nueva línea. Si esa línea contiene alguno de los identificadores leídos antes, se salta (pero puede ocurrir un error, leer más abajo)
- Si un identificador se vuelve a repetir en las siguientes líneas, se salta (porque está en el patrón $ya_vista)
- El patrón $ya_vista tiene esta forma: campo1x|campo1y|campo1z|...|campo1N, que es como un array, pero en forma de patrón de exp. reg.

Esto realiza el filtrado tal como lo queremos, PERO fallará en el siguiente caso:

Supongamos que la línea X contiene un campo -distinto del primero- llamado 'campoXY'.

Si... más adelante... leemos la línea Y, y resulta que su primer campo es justamente 'campoXY', la línea X leída antes no es filtrada (porque entonces no se sabía que existiera una línea Y).

Entonces... si la regla básica es que hay que filtrar todas las líneas para extraer aquellas que contengan cualquiera de los primeros campos de todas las líneas, no queda más remedio que hacer dos pasadas:

- En la primera pasada, nos hacemos con todos los campos1, y creamos el patrón
- En la segunda pasada, filtramos las líneas que coinciden con el patrón, EXCEPTO si el patrón coincide con el primer campo de la línea. Si la línea no coincide con todo esto, grabamos la línea en el archivo resultado
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: Eliminar datos redundantes de una tabla

Notapor Alfumao » 2016-03-21 09:39 @444

¡Gracias, explorer!

Consideraré cuidadosamente lo que has expuesto en tu última respuesta para plantear el programa.

:) :wink:
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514


Volver a Intermedio

¿Quién está conectado?

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