Прочитайте случайные строки из огромного файла CSV в Python

У меня есть довольно большой файл CSV (15 Гб), и мне нужно прочитать около 1 миллиона случайных строк. Насколько я могу видеть – и реализовать – утилита CSV в Python только позволяет последовательно итератировать в файле.

Очень много памяти, чтобы прочитать весь файл в памяти, чтобы использовать какой-то случайный выбор, и очень много времени, чтобы пройти через весь файл, отбросить некоторые значения и выбрать другие, поэтому в любом случае нужно выбрать какую-либо случайную строку из файла CSV и читать только эту строку?

Я пробовал без успеха:

import csv with open('linear_e_LAN2A_F_0_435keV.csv') as file: reader = csv.reader(file) print reader[someRandomInteger] 

Пример файла CSV:

 331.093,329.735 251.188,249.994 374.468,373.782 295.643,295.159 83.9058,0 380.709,116.221 352.238,351.891 183.809,182.615 257.277,201.302 61.4598,40.7106 

10 Solutions collect form web for “Прочитайте случайные строки из огромного файла CSV в Python”

 import random filesize = 1500 #size of the really big file offset = random.randrange(filesize) f = open('really_big_file') f.seek(offset) #go to random position f.readline() # discard - bound to be partial line random_line = f.readline() # bingo! # extra to handle last/first line edge cases if len(random_line) == 0: # we have hit the end f.seek(0) random_line = f.readline() # so we'll grab the first line instead 

Как отметил @AndreBoos, этот подход приведет к предвзятому выбору. Если вы знаете минимальную и максимальную длину строки, вы можете удалить это смещение, выполнив следующие действия:

Предположим (в этом случае) min = 3 и max = 15

1) Найдите длину (Lp) предыдущей строки.

Тогда, если Lp = 3, линия наиболее предвзята. Следовательно, мы должны принимать его в 100% случаев. Если Lp = 15, линия наиболее предвзята. Мы должны принимать его только в 20% случаев, так как он скорее всего выбран.

Мы достигаем этого, произвольно сохраняя линию X% времени, когда:

X = min / Lp

Если мы не будем держать линию, мы делаем еще один случайный выбор, пока наш бросок кости не станет хорошим. 🙂

У меня этот довольно большой файл CSV (15 Гб), и мне нужно прочитать около 1 миллиона случайных строк

Предполагая, что вам не нужно ровно 1 миллион строк и заранее знать количество строк в вашем файле CSV, вы можете использовать выборку коллектора для извлечения своего случайного подмножества. Просто итетерируйте свои данные, и для каждой линии определите шансы выбора линии. Таким образом вам нужен только один проход ваших данных.

Это хорошо работает, если вам нужно часто извлекать случайные выборки, но фактический набор данных изменяется редко (поскольку вам нужно будет отслеживать количество записей каждый раз при изменении набора данных).

 chances_selected = desired_num_results / total_entries for line in csv.reader(file): if random() < chances_selected: result.append(line) 

Вы можете использовать вариацию вероятностного метода для выбора случайной строки в файле.

Вместо того, чтобы просто сохранить один выбранный номер, вы можете сохранить буфер размером C Для каждого номера строки n в файле с N строками вы хотите выбрать эту строку с вероятностью C/n (вместо оригинала 1/n . Если номер выбран, вы выбираете случайное местоположение из C- для выселения.

Вот как это работает:

 import random C = 2 fpath = 'somelines.txt' buffer = [] f = open(fpath, 'r') for line_num, line in enumerate(f): n = line_num + 1.0 r = random.random() if n <= C: buffer.append(line.strip()) elif r < C/n: loc = random.randint(0, C-1) buffer[loc] = line.strip() 

Для этого требуется один проход через файл (поэтому это линейное время) и возвращает ровно C строк из файла. Каждая строка будет иметь вероятность выбора C/N

Чтобы убедиться, что это работает, я создал файл с 5 строками, содержащими a, b, c, d, e. Я пробежал код 10 000 раз с C = 2. Это должно привести к равномерному распределению 5 возможных 2 (так 10) возможных вариантов. Результаты:

 a,b: 1046 b,c: 1018 b,e: 1014 a,c: 1003 c,d: 1002 d,e: 1000 c,e: 993 a,e: 992 a,d: 985 b,d: 947 

Другое решение возможно, если вы знаете общее количество строк – генерируете 1 миллион случайных чисел ( random.sample(xrange(n), 1000000) ) до общего количества строк в виде набора, а затем используйте:

 for i, line in enumerate(csvfile): if i in lines_to_grab: yield line 

Это даст вам ровно 1 миллион строк беспристрастно, но вам нужно иметь количество строк заранее.

Если строки действительно имеют формат .csv и НЕ фиксированное поле, то нет, нет. Вы можете просканировать файл через один раз, индексируя смещения байтов для каждой строки, а затем, когда позже нужно использовать только набор индексов, но нет априорного предсказания точного местоположения символа \ n для завершения строки для произвольных файлов csv.

Если вы хотите много раз брать случайные строки (например, мини-партии для машинного обучения), и вы не пропустите сканирование через огромный файл один раз (без его загрузки в память), тогда вы можете создать список линейных делений и используйте стремление быстро схватить линии (исходя из ответа Марии Зверины).

 # Overhead: # Read the line locations into memory once. (If the lines are long, # this should take substantially less memory than the file itself.) fname = 'big_file' s = [0] linelocs = [s.append(s[0]+len(n)) or s.pop(0) for n in open(fname)] f = open(fname) # Reopen the file. # Each subsequent iteration uses only the code below: # Grab a 1,000,000 line sample # I sorted these because I assume the seeks are faster that way. chosen = sorted(random.sample(linelocs, 1000000)) sampleLines = [] for offset in chosen: f.seek(offset) sampleLines.append(f.readline()) # Now we can randomize if need be. random.shuffle(sampleLines) 

Вы можете переписать файл с фиксированными записями, а затем выполнить произвольный доступ к промежуточному файлу позже:

 ifile = file.open("inputfile.csv") ofile = file.open("intermediatefile.csv",'w') for line in ifile: ofile.write(line.rstrip('\n').ljust(15)+'\n') 

Затем вы можете:

 import random ifile = file.open("intermediatefile.csv") lines = [] samples = random.sample(range(nlines)) for sample in samples: ifile.seek(sample) lines.append(ifile.readline()) 

Требуется больше дискового пространства, и первая программа может занять некоторое время, но она позволяет неограниченный более поздний случайный доступ к записям со вторым.

Если вы можете поместить эти данные в базу данных sqlite3, выбор нескольких случайных строк тривиален. Вам не нужно предварительно читать или писать строки в файле. Так как файлы данных sqlite являются двоичными, файл данных будет на 1/3 до 1/2 меньше, чем текст CSV.

Вы можете использовать скрипт типа ЭТО для импорта CSV-файла или, что еще лучше, просто напишите свои данные в таблицу базы данных. SQLITE3 является частью дистрибутива Python.

Затем используйте эти инструкции для получения 1 000 000 случайных строк:

 mydb='csv.db' con=sqlite3.connect(mydb) with con: cur=con.cursor() cur.execute("SELECT * FROM csv ORDER BY RANDOM() LIMIT 1000000;") for row in cur.fetchall(): # now you have random rows... 
 # pass 1, count the number of rows in the file rowcount = sum(1 for line in file) # pass 2, select random lines file.seek(0) remaining = 1000000 for row in csv.reader(file): if random.randrange(rowcount) < remaining: print row remaining -= 1 rowcount -= 1 

В этом методе мы генерируем случайное числовое множество, число элементов которого равно числу строк, которые должны быть считаны, причем его диапазон представляет собой количество строк, присутствующих в данных. Затем он сортируется от наименьшего до самого большого и сохраняется.

Затем файл csv читается по строкам, и для обозначения номера строки используется строка line_counter . Этот line_counter затем проверяется первым элементом списка отсортированных случайных чисел, и если они одинаковы, то эта конкретная строка записывается в новый файл csv, а первый элемент удаляется из списка, а второй элемент заменяет сначала, и цикл продолжается.

 import random k=random.sample(xrange(No_of_rows_in_data),No_of_lines_to_be_read) Num=sorted(k) line_counter = 0 with open(input_file,'rb') as file_handle: reader = csv.reader(file_handle) with open(output_file,'wb') as outfile: a=csv.writer(outfile) for line in reader: line_counter += 1 if line_counter == Num[0]: a.writerow(line) Num.remove(Num[0]) if len(Num)==0: break 
  • Прочитайте небольшой случайный образец из большого CSV-файла в фрейм данных Python
  • случайная итерация в Python
  • Лучший способ рандомизировать список строк в Python
  • Существует ли распределение случайных чисел, которое подчиняется Закону Бенфорда?
  • Генерация случайных текстовых строк заданного шаблона
  • Генерация больших простых чисел в python
  • Генерирование случайных векторов евклидовой нормы <= 1 в Python?
  • Рекомендации для квази-случайных последовательностей для низкого расхождения (например, Sobol) в Python / SciPy?
  •  
    Interesting Posts for Van-Lav

    Отображение указателя в Boost.Python

    Автоматически масштабировать ylim и xlim в Matplotlib

    Множество расстояний до списка (строка, столбец, расстояние)

    фатальная ошибка: файл «Python.h» не найден при установке opencv

    Кратчайшая повторяющаяся суб-строка

    Устранение неполадок reportlab heisenbug

    Есть ли стандартный способ убедиться, что скрипт python будет интерпретироваться python2, а не python3?

    ImportError после успешной установки

    Задайте запрос SQLAlchemy, укажите имена столбцов

    Ошибка Python Pysftp

    Как создать пул соединений mysql или любой другой способ инициализации нескольких баз данных?

    отправить выбранное значение из форм Django в views.py

    Существует ли эквивалент matlab 'idealfilter' для Python в Scipy (или других библиотеках)?

    Как чисто индексировать массивы numpy массивами (или что-нибудь еще, что поддерживает добавление, чтобы оно могло быть смещено)

    Альтернативы Selenium / Webdriver для заполнения полей при сглаживании без использования Python?

    Python - лучший язык программирования в мире.