使用SQLite的NumPy数组
我在Python中见到的最常用的SQLite接口是sqlite3
,但是有没有什么东西可以很好地与NumPy数组或记录数组(recarrays)配合使用呢?我指的是那种能够识别数据类型,不需要一行一行插入数据,并且可以提取成NumPy(rec)数组的工具……有点像R语言中的SQL函数,比如RDB
或sqldf
库,如果有人熟悉的话(它们可以将整个表或表的子集导入/导出/追加到R的数据表中)。
4 个回答
1
这看起来有点老旧,但有没有什么原因让你不能直接用fetchall()呢?这样的话,直接在声明时初始化numpy就可以了。
3
Doug 提出的使用 redis 的建议挺不错的,但我觉得他的代码有点复杂,因此速度也比较慢。对我来说,我需要在不到十分之一秒的时间内,把大约一百万个浮点数的方阵进行序列化(也就是把数据转换成可以存储的格式)并写入,然后再读取并反序列化(把存储的数据转换回原来的格式),所以我这样做:
写入时:
snapshot = np.random.randn(1024,1024)
serialized = snapshot.tobytes()
rs.set('snapshot_key', serialized)
然后读取时:
s = rs.get('snapshot_key')
deserialized = np.frombuffer(s).astype(np.float32)
rank = np.sqrt(deserialized.size).astype(int)
snap = deserialized(rank, rank)
你可以用 ipython 进行一些基本的性能测试,使用 %time 命令,但无论是 tobytes 还是 frombuffer 都不会超过几毫秒。
9
为什么不试试redis呢?
你感兴趣的两个平台都有相应的驱动程序可用——Python(用的是redis,可以通过包索引2找到),还有R(用的是rredis,可以在CRAN上找到)。
redis的聪明之处并不是它能神奇地识别NumPy数据类型,让你像使用本地数据类型一样插入和提取多维NumPy数组,而是它让你用几行代码就能轻松创建这样的接口,这才是它的真正魅力。
关于在Python中使用redis的教程有好几个,其中DeGizmo博客上的那篇特别不错。
import numpy as NP
# create some data
A = NP.random.randint(0, 10, 40).reshape(8, 5)
# a couple of utility functions to (i) manipulate NumPy arrays prior to insertion
# into redis db for more compact storage &
# (ii) to restore the original NumPy data types upon retrieval from redis db
fnx2 = lambda v : map(int, list(v))
fnx = lambda v : ''.join(map(str, v))
# start the redis server (e.g. from a bash prompt)
$> cd /usr/local/bin # default install directory for 'nix
$> redis-server # starts the redis server
# start the redis client:
from redis import Redis
r0 = Redis(db=0, port=6379, host='localhost') # same as: r0 = Redis()
# to insert items using redis 'string' datatype, call 'set' on the database, r0, and
# just pass in a key, and the item to insert
r0.set('k1', A[0,:])
# row-wise insertion the 2D array into redis, iterate over the array:
for c in range(A.shape[0]):
r0.set( "k{0}".format(c), fnx(A[c,:]) )
# or to insert all rows at once
# use 'mset' ('multi set') and pass in a key-value mapping:
x = dict([sublist for sublist in enumerate(A.tolist())])
r0.mset(x1)
# to retrieve a row, pass its key to 'get'
>>> r0.get('k0')
'63295'
# retrieve the entire array from redis:
kx = r0.keys('*') # returns all keys in redis database, r0
for key in kx :
r0.get(key)
# to retrieve it in original form:
A = []
for key in kx:
A.append(fnx2(r0.get("{0}".format(key))))
>>> A = NP.array(A)
>>> A
array([[ 6., 2., 3., 3., 9.],
[ 4., 9., 6., 2., 3.],
[ 3., 7., 9., 5., 0.],
[ 5., 2., 6., 3., 4.],
[ 7., 1., 5., 0., 2.],
[ 8., 6., 1., 5., 8.],
[ 1., 7., 6., 4., 9.],
[ 6., 4., 1., 3., 6.]])