У меня есть следующая строка, которую я хотел бы закодировать по Хаффману и эффективно сохранить в битовый массив:
>>> print sequence
GTCAGGACAAGAAAGACAANTCCAATTNACATTATG|
Частоты символов в последовательности
:
>>> print freqTuples
[(0.40540540540540543, 'A'), (0.1891891891891892, 'T'), (0.16216216216216217, 'C'), (0.16216216216216217, 'G'), (0.05405405405405406, 'N'), (0.02702702702702703, '|')]`
Я перевожу это в словарь кода Хаффмана:
>>> print codeDict
{'A': '1', 'C': '010', 'G': '001', 'N': '0110', 'T': '000', '|': '0111'}
Затем я использовал пакет Python bitstring
для перевода строки, символ за символом, в экземпляр класса BitArray
, который я называю bitArray
, который содержит биты для каждого символа, закодированного соответствующим кодом Хаффмана:
>>> print bitArray.bin
0b001000010100100110101100111100110101101100000100101100000001101010100000010000010111
Вот битовый массив в байтах:
>>> print bitArray.tobytes()
!I\254\363[^D\260^Z\240Ap
Я должен использовать tobytes ()
вместо байтов
, поскольку генерируемый мной битовый массив не делится равномерно на 8-битные сегменты.
Когда я вычисляю эффективность хранения представления BitArray
(соотношение размеров битового массива и входной строки), я получаю худшую производительность, чем если бы я оставил входную строку незакодированной:
>>> sys.getsizeof(bitArray.tobytes()) / float(len(sequence))
1.2972972973
Правильно ли я измеряю эффективность хранения? (Если я кодирую более длинные входные строки, это соотношение улучшается, но кажется, что оно приближается к асимптотическому пределу около 0,28. Я хотел бы подтвердить, правильный ли это способ измерения.)
Изменить
Следующее два подхода дают разные ответы:
>>> print len(bitArray.tobytes()) / float(len(mergedSequence))
0.297297297297
>>> print bitArray.len / (8.*len(mergedSequence))
0.283783783784
Я не уверен, чему верить. Но в процессе записи данных в хранилище, я думаю, мне понадобится байтовое представление, что заставляет меня склоняться к выбору первого результата.