Hace 9 años | Por --171278--
Publicado hace 9 años por --171278--

Buenas.

Tengo que obtener una fila al azar de un fichero csv en python. El fichero tiene como 3 millones de filas donde hay datos.
Si recorro todoas y luego añado una al azar tarda como un minuto y medio.

¿Se os ocurre alguna forma de hacerlo más rápido?

Había pensado en que elegir un número al azar al inicio y que leyera hasta esa fila pero claro si sale grande tardará igual.

Comentarios

D

No parece complejo el phyton este

chisme para leer una linea aleatoria desde un fichero F

import sys,random

with open(sys.argv[1],"r") as f #abrimos er fishero
f.seek(0,2) # vamos al final
bytes = f.tell() # Averiguamos el tamaño
f.seek(int(bytes*random.random())) #Movemos el puntero a un sitio aleatorio


while True: #buscamos hacia atras hasta encontrar el principio del fichero
f.seek(-2,1)
ch = f.read(1)
if ch=='n': break #o encontramos un CRLF
if f.tell()==1: break


print f.readline() # Imprimimos la linea

D

#3 un matemático no te dice como leer desde el final, eso lo hace un informático

En serio, no sé programar en python, sólo he dado una solución del problema suponiendo que era posible empezar por el final.

D

#4 No tengo ni idea de Phyton pero todos los lenguajes permiten el acceso aleatorio a un fichero comenzando a leer desde una posición N que puede ser desde el principio y contando hacia adelante o desde el final y contando hacia atrás.

Si todas las filas son del mismo tamaño no hay problema pues multiplicas la posicion (0 based) por el tamaño de la fila y le dices al OS que el file_pointer del fichero desde donde comenzar a leer es el resultado de la multiplicación, pero como es un fichero de texto temo que todas las filas tendrán un tamaño diferente y se indicará el final de fila con un par de caracteres CRLF as usual. En este caso es muy jodido, al menos desde mi punto de vista, pues aunque comencemos a leer desde un punto X del fichero desconocemos cuantas lineas hay antes de ese punto.

Lo mejor en el caso de filas de tamaño aleatorio es mantener un fichero paralelo con las posiciones y el tamaño de las filas (esto último no imprescindible). Cada vez que añadimos una fila añadimos a su vez la posición del fichero donde se insertó y la longitud. Como el tamaño de los indices sí que es fijo aquí podemos usar la multiplicación para recuperar el puntero N y saber donde tenemos que comenzar a leer en el fichero de texto. Sería como una base de datos rudimentaria.

D

#5 En efecto ^-^ el problema es que no todas las filas son del mismo tamaño y no siguen un patrón

D

#0 digamos que hay n filas.


elige el numero al azar, llamemosle x, y si sale menor que n/2 lees hasta esa fila; si sale mayor que n/2 lees hasta la fila n-x comenzando por el final.

Reduces el tiempo de lectura hasta como máximo la mitad.

Y tal vez puedas iterar.

D

#2 la idea es buena, pero como lees desde el final?

D

He solucionado el problema transformando el fichero a una base de datos sqlite3...pero dejo esto abierto porque el tema puede ser interesante

gallir

#1 El seek/lseek es lo más rápido, te posicionas directamente donde quieras. Si las filas son de longitud variable, busca el final y coge la siguiente.