提问人:DazzRick 提问时间:8/7/2023 最后编辑:DazzRick 更新时间:8/8/2023 访问量:107
在 Numpy 数组中存储浮点数的高速和低内存方式
High-speed and low-memory way to store a float number inside a Numpy array
问:
我有这个数字:.我想将其保存在 Numpy 数组中,我认为虽然位数较低,但它仍然更好。这是对的吗?19576.4125
我试图在一半和一人中保存,但我不知道为什么它会改变数字。
- 我的号码:
19576.4125
- 半:
19580.0
- 单:
19576.412
这个数字是由我创建的用于访问浮点数的方法生成的。我可以使用时间戳,但我不需要秒和毫秒,所以我尝试创建自己的方法,只保存日期、小时和分钟。(我的数据库不接受 s 和 s)。datetime
datetime
timedelta
这是我的生成器方法:
from datetime import datetime
def get_timestamp() -> float:
now = datetime.now()
now.replace(microsecond=0, second=0)
_1970 = datetime(1970, 1, 1, 0, 0, 0)
td = now - _1970
days = td.days
hours, remainder = divmod(td.seconds, 3600)
minutes, second = divmod(remainder, 60)
timestamp = days + hours / 24 + minutes / 1440
return round(timestamp, 4)
我如何创建数组:
from numpy import array, half, single
__td = get_timestamp()
print(__td)
__array = array([__td], dtype=half)
print(type(__array[0]))
print(__array[0])
__array = array([__td], dtype=single)
print(type(__array[0]))
print(__array[0])
已编辑 08/07 11h02 AM
您好,这样的评论说,我认为这个数字不能保存在一半或单一类型中。那么,如何以更好的性能保存这个数字呢?最好像 int 并乘以 10000、float64 或字符串一样保存?
而不是,我不想要更好的方法来保存这个具有更好性能的浮点数。但感谢您的其他回复。datetime
答:
我觉得你的标题问题和正文是不同的。 如果你的目标是制作一个函数,使“日期时间转到浮点数”,并可能稍后返回日期时间,你可以使用这种方法作为替代方法:
import datetime
# convert to a float timestamp
ts = datetime.datetime.now().timestamp()
# convert back to datetime format
datetime.datetime.fromtimestamp(ts)
我修改了您的函数以采用时间温度
In [48]: def get_timestamp(now) -> float:
...: #now = datetime.now()
...: now.replace(microsecond=0, second=0)
...
...: return round(timestamp, 4)
...:
并列出了日期:
In [49]: alist = [datetime.now() for _ in range(1000)]
In [50]: timeit alist = [datetime.now() for _ in range(1000)]
885 µs ± 2.27 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
并定时你的函数,以创建一个数组:
In [51]: arr = np.array([get_timestamp(d) for d in alist])
In [52]: timeit arr = np.array([get_timestamp(d) for d in alist])
7.7 ms ± 16.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [53]: arr.nbytes
Out[53]: 8000
并做了同样的事情,但使用 numpy 自己转换为 8 字节元素:
In [54]: barr = np.array(alist,dtype='datetime64[m]')
In [55]: barr.nbytes
Out[55]: 8000
In [56]: timeit barr = np.array(alist,dtype='datetime64[m]')
7.87 ms ± 38.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
所以转换时间基本相同。因此,从计算和记忆来看,您的函数同样出色。
另存为 4 字节元素(float 或 int)会减少内存使用,但除非您遇到数百万个值的内存错误,否则这种努力很少值得。
datetime64
已经完成了两种方式的转换。我想界面也很好,尽管似乎有自己的日期时间格式和技巧。毕竟,它是为处理时间序列而设计的。pandas
pandas
熊猫
In [64]: import pandas as pd
In [65]: df = pd.DataFrame({'a':arr, 'b':barr})
In [66]: df
Out[66]:
a b
0 19576.3799 2023-08-07 09:07:00
1 19576.3799 2023-08-07 09:07:00
2 19576.3799 2023-08-07 09:07:00
3 19576.3799 2023-08-07 09:07:00
4 19576.3799 2023-08-07 09:07:00
.. ... ...
995 19576.3799 2023-08-07 09:07:00
996 19576.3799 2023-08-07 09:07:00
997 19576.3799 2023-08-07 09:07:00
998 19576.3799 2023-08-07 09:07:00
999 19576.3799 2023-08-07 09:07:00
[1000 rows x 2 columns]
In [67]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 a 1000 non-null float64
1 b 1000 non-null datetime64[s]
dtypes: datetime64[s](1), float64(1)
memory usage: 15.8 KB
有趣的是,如果我将时间戳列表直接保存到数据帧中,它会更快
In [81]: df = pd.DataFrame({'c':alist})
In [82]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 1 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 c 1000 non-null datetime64[ns]
dtypes: datetime64[ns](1)
memory usage: 7.9 KB
In [83]: timeit df = pd.DataFrame({'c':alist})
5.29 ms ± 22.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
评论
datetime64[m]