5 de julio de 2019

Consultas eficientes sobre ficheros TSV con SQL

Hola,
estos dias está de visita mi colega Valerie y me preguntaba si había alguna manera de seleccionar de manera eficiente filas de un fichero con millones de líneas, en su caso con columnas separadas por tabuladores (TSV). Yo le sugerí una base de datos relacional y como ella escribe sobre todo en python lo hicimos así, con sqlite:

import sqlite3

# local file with data to populate SQL db
data_file = 'data4sql.tab'

# persistent database file to be created, returns a Connection
conn = sqlite3.connect('example.sqlite.db')

# Cursor object to perform SQL commands on that connection
c = conn.cursor()

# create a table as a list of columns and their types (NULL, INTEGER, REAL, TEXT, BLOB)
# NOTE: the columns should match those in data_file
tb_name = 'mytable'
c.execute('CREATE TABLE {tn}\
             (IMG text, scaffold_id text, GC real, length integer, locus_tag text,\
             IMG_gene_id text, gene_type text, gene_start integer, gene_stop integer,\
             gene_length integer, depth real)'.format(tn=tb_name))

with open(data_file) as fin:
    for line in fin:
        cols = line.rstrip().split("\t")

        # make sure empty values are changed to NULL
        cols=[None if x=='' else x for x in cols]
        
        # Insert a row of data
        c.execute("INSERT INTO {tn} VALUES (?,?,?,?,?,?,?,?,?,?,?)".format(tn=tb_name),cols[0:11])

# save (commit) the changes
conn.commit()

# example queries, any valid SELECT SQL can be used
c.execute('SELECT * FROM {tn} WHERE depth >10'.\
        format(tn=tb_name))
for line in c.fetchall():
   print(line)

# close and exit
conn.close()

En realidad esto se debería separar en dos programas, uno para crear la base de datos y otro para hacer consultas sobe ella. El código es sencillo, pero deberás conocer un mínimo de sintaxis SQL para entender cómo crear tablas, con sus tipos, y cómo hacer consultas. Fíjate que los valores perdidos los sustituimos por un objeto None,
saludos,
Bruno y Valerie

3 comentarios:

  1. Do you have any experience on performing similar tasks in Perl? Which library could be suitable? What could be the main differences from Python where one must pay attention?

    Cordialmente y gracias por su artículos interesantes

    ResponderEliminar
  2. Es muy similar en Perl,usando el módulo DBI: https://code-maven.com/slides/perl-programming/database-using-dbi

    ResponderEliminar
  3. Gracias Bruno. Voy a probar eso.

    ResponderEliminar