Estou tentando escrever uma matriz de dados em um arquivo binário com a intenção de acessar posteriormente esse arquivo para localizar dados. Procurei online e encontrei vários métodos para salvar dados usando df.to_pickle, struct.pack, np.to_bytes(). Agora vem a parte de lê-lo. Encontrei outros posts solicitando leitura, mas até agora nenhum ajudou na recuperação dos dados. Tenho a impressão de que isso pode ter a ver com a forma como comprimo os dados.
formato de dados
0 1 2 3 . . . n
0
1 -0.111
2 0.84 0.1
3 0.25 0.6 -0.2
.
.
.
n
Este é um conjunto de dados de comparação, portanto, no cruzamento das variáveis, é 1. Devido a restrições de alocação de memória e tamanho dos dados, resultou na geração de uma tabela de dados como esta em um arquivo de texto. Armazenar na memória não foi possível porque n pode ser muito grande.
Para converter para binário, leio cada linha do texto, converto os valores para o formato correto e uso numpy.array.tobytes()
save_path = Path(save_loc)
save_data = save_path.open()
with load_data_path.open() as data_chunk:
for idx, data in enumerate(data_chunk,0):
if idx == 0:
save_data.write(b"\n")
continue
dlist = data.strip("\n").split(",")
d_array = [np.float64(x) for x in dlist]
save_data.write(d_array.tobytes())
save_data.close()
para ler os dados, tentei usar np.frombuffer e struct.unpack mas ambos resultaram em erros. Além disso, pelo que entendi, a leitura colocaria todos os dados na memória, o que não funcionaria para os meus dados. Optei por abrir o binário usando path, localizando a linha e lendo diretamente. Aqui está o código
find_line = 7984
load_data = Path(data_loc)
with load_data.open("rb") as data_chunk:
for idx, data in enumerate(data_chunk,0):
if idx < find_line:
continue
else:
my_line = np.frombuffer(data, "f", idx)
break
isso, no entanto, resulta em um erro
ValueError: buffer is smaller than requested size
editar: Após uma investigação mais aprofundada, encontrei três problemas em meu código. 1 é que minha formatação estava incorreta ao usar o frombuffer. Como codifico como np.float64, chamar "f" tenta retornar um float32.
a segunda é que presumi que escrever o arquivo binário manteria os blocos de escrita (com um "\n" como delimitador para cada bloco), mas este não é o caso, pois quando tentei olhar minhas primeiras linhas, cada uma delas tinha 2.000 bits quando deveriam ter apenas ~ 16.
finalmente, parece que "\n" está sendo adicionado em algum lugar do processo, pois ao carregar mais abaixo na lista, encontro mais valores "\n" que dividem os bytes. Eu deveria ter cerca de 60.000 bytes para serem carregados, mas uma quebra de linha retorna apenas cerca de 2.500 bytes
Em um arquivo binário, o
b'\n'
caractere (valor de byte 0x0A) pode ocorrer nos dados flutuantes binários, portanto, delimitadores não são necessários ou desejados.De acordo com os comentários esclarecedores na pergunta do OP, cada linha (numerada de 0) contém colunas "line#". A
numpy.float64
tem 8 bytes de comprimento. Leia os bytes "line# * 8" e acompanhe o número da linha.Use
csv.reader
para simplificar a leitura da entrada.input.csv (exemplo, observe a primeira linha em branco intencional):
Código (Python 3.12):
Saída: