Самый быстрый способ записать файл с помощью h5py

Прежде всего, я прочитал тему «Самый быстрый способ записи файла hdf5 с Python?", но это не очень помогло.

Я пытаюсь загрузить файл размером около 1 ГБ (матрица размером (70133351,1)) в структуре h5f5.

Довольно простой код, но медленный.

import h5py
f = h5py.File("8.hdf5", "w")
dset = f.create_dataset("8", (70133351,1))

myfile=open("8.txt")

for line in myfile:
   line=line.split("\t")
   dset[line[1]]=line[0]

myfile.close()
f.close()

У меня есть уменьшенная версия матрицы с 50 МБ, и я пробовал тот же код, и он не был завершен через 24 часа.

Я знаю способ сделать это быстрее, чтобы избежать "цикла for". Если бы я использовал обычный Python, я бы использовал хэш-понимание. Однако, похоже, он здесь не подходит.

Я могу запросить файл позже:

f = h5py.File("8.hdf5")
h=f['8']
print 'GFXVG' in h.attrs 

Что ответило бы мне «Верно», учитывая, что GFXVG находится на ключах в h

У кого-нибудь есть идеи?

Пример части файла:

508 LREGASKW
592 SVFKINKS
1151        LGHWTVSP
131 EAGQIISE
198 ELDDSARE
344 SQAVAVAN
336 ELDDSARF
592 SVFKINKL
638 SVFKINKI
107 PRTGAGQH
107 PRTGAAAA

Спасибо


person user3780518    schedule 26.06.2014    source источник
comment
из сообщения, которое вы цитируете, прочитайте [...] в кусках настолько больших, насколько вы можете удерживать, и писать ип куски тоже.   -  person toine    schedule 26.06.2014
comment
Привет Тойне. Спасибо, что указали на это. Не могли бы вы показать мне пример?   -  person user3780518    schedule 26.06.2014
comment
можешь выложить пару строк данных из файла 8.txt.   -  person toine    schedule 26.06.2014
comment
Конечно, это табличный файл. Идея в том, что элемент во втором столбце является первичным ключом, и мне нужен быстрый способ получить к нему доступ без необходимости каждый раз загружать данные в хэш. Я добавил пример сверху   -  person user3780518    schedule 26.06.2014
comment
Я думаю, проблема в том, что вы не переводите индекс в int   -  person daniel    schedule 26.06.2014
comment
О, @user3780518, только что увидел твой комментарий. Извините за неправильное прочтение. Наборы данных h5py представляют собой массивы, а не хеш-таблицы. Возможно, вы захотите написать здесь свою собственную хеш-функцию, которая может отображать эти str в int, чтобы вы могли индексировать набор данных.   -  person daniel    schedule 26.06.2014
comment
Используя конечный продукт моего медленного кода, я мог бы использовать структуру как хэш, загрузив файл как: f = h5py.File("8.hdf5") h=f['8'] print 'GFXVG' in h.attrs f.close()   -  person user3780518    schedule 27.06.2014
comment
h.attrs будет словарем, но не рекомендуется использовать attrs в качестве набора данных. Наборы данных в hdf5 можно рассматривать как массивы numpy, и я думаю, что в текущем подходе есть фундаментальная проблема. То, что он работает для вашего теста, не означает, что он гарантированно сработает.   -  person daniel    schedule 27.06.2014
comment
Я понимаю. Итак, есть ли другой подход (даже без h5py), чтобы не читать каждый раз большой файл и загружать его в диктофон? Каким-то образом загружает файл куда-то и читает большой файл как диктовку? Это боль в шее каждый раз, когда я запускаю свою программу, мне приходится читать большой файл в диктовке. Я думал, что сбегу от этого с помощью h5py.   -  person user3780518    schedule 27.06.2014
comment
вы можете записать dict на диск и загрузить его, когда вам это нужно.   -  person toine    schedule 27.06.2014
comment
Ага. Спасибо, это работает для меня.   -  person user3780518    schedule 27.06.2014


Ответы (3)


Вы можете загрузить все данные в numpy array с помощью loadtext и использовать их для создания экземпляра набора данных hdf5.

import h5py
import numpy as np

d = np.loadtxt('data.txt', dtype='|S18')

которые возвращаются

array([['508.fna', 'LREGASKW'],
   ['592.fna', 'SVFKINKS'],
   ['1151.fna', 'LGHWTVSP'],
   ['131.fna', 'EAGQIISE'],
   ['198.fna', 'ELDDSARE'],
   ['344.fna', 'SQAVAVAN'],
   ['336.fna', 'ELDDSARF'],
   ['592.fna', 'SVFKINKL'],
   ['638.fna', 'SVFKINKI'],
   ['107.fna', 'PRTGAGQH'],
   ['1197.fna', 'ELDDSARR'],
   ['1309.fna', 'SQTIYVWF'],
   ['974.fna', 'PNNLRFIA'],
   ['230.fna', 'IGKVYHIE'],
   ['76.fna', 'PGVHSVWV'],
   ['928.fna', 'HERGGAND'],
   ['520.fna', 'VLKTDTTG'],
   ['1290.fna', 'EAALDLHR'],
   ['25.fna', 'FCSILGVV'],
   ['284.fna', 'YHKLTFED'],
   ['1110.fna', 'KITSSSDF']], 
  dtype='|S18')

а потом

h = h5py.File('data.hdf5', 'w')
dset = h.create_dataset('data', data=d)

что дает:

<HDF5 dataset "init": shape (21, 2), type "|S18">
person toine    schedule 26.06.2014
comment
Мне нравится использовать loadtxt, я всегда забываю об этом. Я думаю, что в данных примера столбец 0 равен int, что, конечно, можно было бы изменить, передав ожидаемые dtypes в loadtxt. - person daniel; 26.06.2014
comment
формат данных изменился в процессе видимо.. :) - person toine; 26.06.2014
comment
Спасибо @toine, но с помощью вашего метода я не могу запрашивать свои данные, как мог бы, используя структуру, созданную с использованием медленного кода. f = h5py.File("5.hdf5") h=f['5'] print 'GFXVG' in h.attrs - person user3780518; 27.06.2014
comment
Я обновил свой вопрос вверху. Я считаю, что теперь это более ясно - person user3780518; 27.06.2014

Поскольку это всего лишь ГБ, почему бы сначала не загрузить его полностью в память? Обратите внимание: похоже, вы также индексируете dset с помощью str, что, вероятно, и является проблемой.

Я только что понял, что неправильно понял первоначальный вопрос, извините за это. Похоже, ваш код пытается использовать индекс 1, который выглядит как строка, в качестве индекса? Возможно там опечатка?

import h5py
from numpy import zeros

data = zeros((70133351,1), dtype='|S8') # assuming your strings are all 8 characters, use object if vlen

with open('8.txt') as myfile: 
   for line in myfile:
       idx, item = line.strip().split("\t")
       data[int(line[0])] = line[1]

with h5py.File('8.hdf5', 'w') as f:
    dset = f.create_dataset("8", (70133351, 1), data=data)
person daniel    schedule 26.06.2014
comment
Спасибо за ответ, Даниил. Однако я считаю, что это не решает мою проблему. Как я уже сказал выше, мне нужно, чтобы второй столбец был моим первичным ключом, и так, как вы это сделали, вы используете числа в качестве первичных ключей. Здесь число не может быть первичным ключом, потому что оно повторяется (может быть, не в том маленьком примере, о котором я говорил; мой плохой). Кстати, это должно быть data[int(idx)] =item, а не data[int(line[1])] = line[0] - person user3780518; 26.06.2014
comment
Я обновил свой вопрос вверху. Я считаю, что теперь это более ясно - person user3780518; 27.06.2014

В итоге я использовал полку библиотеки (Pickle и полка для хранения больших словарей в Python) для хранения большого словаря в файле. Мне потребовалось 2 дня только для того, чтобы записать хеш в файл, но как только это было сделано, я могу очень быстро загружать и получать доступ к любому элементу. В конце концов, мне не нужно читать свой большой файл и записывать всю информацию в hass и делать все, что я пытался сделать с хэшем.

Проблема решена!

person user3780518    schedule 01.07.2014