You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将Numpy savetxt的存储类型从int16改为int8?

解决Numpy savetxt存储二进制值时文件偏大的问题

你提到的情况其实是对np.savetxt的工作逻辑有点误解——savetxt是将数组保存为文本文件,并不存在“用int16数据类型存储”的说法,你看到的每个值占2字节,本质是默认格式输出带来的额外字符(比如空格、换行符)导致的。咱们一步步拆解问题和解决方案:

为什么原代码会让文件变大?

当你用fmt='%d'时,Numpy会按默认的文本格式规则输出:

  • 对于一维数组,默认每行输出一个元素,格式是数字+换行符(比如0\n),这就占了2字节;
  • 对于二维数组,默认用空格分隔元素,每个元素是数字+空格(比如1 ),同样占2字节,最后一个元素再加换行符。
    哪怕你的数组是np.int8类型,文本存储的是字符形式的数字,和原数组的数值类型没有直接关联——%d只是指定了数字的文本格式,不是二进制存储的类型。

优化方案:让文件更紧凑

1. 调整文本格式参数(适合需要文本文件的场景)

如果你的需求就是存成文本文件(方便查看或其他工具读取),可以通过调整fmtdelimiter参数来压缩空间:
对于只包含0和1的二进制数组,用fmt='%1d'强制每个数字只占1个字符宽度,结合delimiter=''去掉分隔符,这样每个数字仅占1字节:

import numpy as np
import os
import math

def convert_size(size_bytes):
    if size_bytes == 0:
        return "0B"
    size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
    i = int(math.floor(math.log(size_bytes, 1024)))
    p = math.pow(1024, i)
    s = round(size_bytes / p, 2)
    return "%s %s" % (s, size_name[i])

# 测试用的int8二进制数组
Arr = np.random.randint(0, 2, size=100000, dtype=np.int8)
filepath = 'binary_values.txt'

# 原方式
np.savetxt(filepath, Arr, fmt='%d')
print(f"原文件大小: {convert_size(os.path.getsize(filepath))}")

# 优化方式
np.savetxt(filepath, Arr, fmt='%1d', delimiter='')
print(f"优化后文件大小: {convert_size(os.path.getsize(filepath))}")

运行后你会发现优化后的文件大小几乎减半(去掉了换行符或空格的额外字节)。如果是二维数组,这个方式会让每行变成连续的0/1字符串,非常紧凑。

2. 直接存为二进制文件(最省空间)

如果不需要文本格式,只是想高效存储二进制值,那别用savetxt了,直接用Numpy的二进制存储方法:

  • np.save:保存为.npy格式(带数组元数据,方便直接用np.load读取)
  • Arr.tofile():保存为原始二进制文件(仅存数据,最节省空间)

示例代码:

# 存为.npy二进制文件
np.save('binary_values.npy', Arr)
print(f".npy文件大小: {convert_size(os.path.getsize('binary_values.npy'))}")

# 存为原始二进制文件
Arr.tofile('binary_values.raw')
print(f"原始二进制文件大小: {convert_size(os.path.getsize('binary_values.raw'))}")

原始二进制文件的大小正好是数组元素个数×1字节(因为是np.int8),是最节省空间的存储方式。

内容的提问来源于stack exchange,提问作者Mike

火山引擎 最新活动