Muestreando bases de datos

Aunque el concepto de minería de datos esté casi indisolublemente asociado al de bases de datos enormes, en la práctica, el análisis y desarrollo de los modelos se realizan sobre muestras pequeñas.

Esencialmente, para lo que nos ocupa, es pequeño un conjunto de datos que cabe en la RAM de un PC. Actualmente son habituales las máquinas con 1 GB. A modo de comparación, la base de datos de clientes de una de las mayores compañías españolas y en la que trabajé hace un tiempo venía a ocupar 5 GB.

De acuerdo con la ley de Moore, dentro de [18 * log( 5 / 1 ) =] 41,8 meses ya podrá considerarse pequeña.

Pero durante 41,8 meses todavía tendremos que seguir muestreando datos.
Por eso, en este artículo se discuten procedimientos para realizar extracciones aleatorias mediante el muestreo aleatorio simple –la más básica de tales técnicas– de algunos de los gestores de bases de datos con los que es más probable encontrarse:

  • DB2:
    select * from t tablesample bernuilly (p);
  • Mysql:
    select * from t order by rand() limit n;
  • Oracle:
    select * from t sample(p);
  • PostgreSQL:
    select * from t order by random() limit n;
  • SQL Server:
    select top n * from t order by newid();

En las queries anteriores, p representa un porcentaje –un valor entre 0 y 100– y n, un determinado número de filas.
El interesado en realizar muestreos de dicha manera, deberían considerar la información anterior como punto de partida para investigar, según proceda:

  • las opciones adicionales de las que disponen DB2 u Oracle
  • la validez estadística de los muestreos realizados con newid(), rand() o random()
  • tener en cuenta que, a partir de la versión 2005, SQL Server soporta el comando tablesample.

De todos modos, los que no podemos salir de casa sin Python en el pendrive siempre tenemos la opción de volcar las tablas a un fichero de texto y recurrir a una versión del siguiente script:

import random
from sys import argv, exit
import os
if len(argv) == 1:
  print("Argumentos: path fichero umbral")
  exit(1)
random.seed()
path = argv[1]
nom_f_entrada = argv[2]
umbral = float(argv[3])
nom_f_salida = "muest_" + nom_f_entrada
f_entrada = open(os.path.join(path, nom_f_entrada), "r")
f_salida  = open(os.path.join(path, nom_f_salida), "w")
f_salida.write(f_entrada.readline())
l = f_entrada.readline()
while l:
	if (random.random() < umbral):
	f_salida.write(l)
	l = f_entrada.readline()
	f_entrada.close()
f_salida.close()

Nota: esta entrada forma parte de las que aparecían en un antiguo blog mío ya extinto cuyo contenido trato ahora de recuperar. Algo de cuanto en ella se lee, por lo tanto, puede que huela a rancio (como la que se refiere al tamaño de la memoria habitual en los ordenadores). Pero lo más debería todavía poder sostenerse en pie varios años después.

4 comentarios sobre “Muestreando bases de datos

  1. jjgibaja 3 septiembre, 2010 5:39

    ¿El comando en DB2 funciona? Lo comento porque me suena raro ese «bernuilly», que entiendo que debe de referirse a una variable de tipo Bernoulli. ¿Estoy en lo cierto?

  2. datanalytics 3 septiembre, 2010 18:23

    Bueno, como digo en la entrada, es algo que escribí hace ya tiempo. Ahora no tengo acceso a DB2 para probarlo, pero en aquella época sí. Supongo que lo probaría en su día.

    En cualquier caso, el asunto aparece discutido acá: http://db2.aparnaramesh.com/2006/09/data-sampling-in-sql-queries.html. Con probabilidad p/100 (según el ejemplo de arriba) una fila es o no es seleccionada por la consulta.

  3. Freddy López 15 noviembre, 2010 13:48

    Hola. Yo suelo usar SQLite (por medio de SQLiteSpy; aunque esto último no importa). El comando es igual al de postgreSQL. Por si alguien la duda ostenta. Salud.

Los comentarios están desabilitados.