NumPy arrays with SQLite



我在Python中看到的最常见的SQLite接口是sqlite3,但是有什么可以很好地与NumPy数组或recarrays一起工作吗?我的意思是一个识别数据类型,不需要插入一行一行,并提取到NumPy (rec)数组…?有点像R的SQL函数在RDBsqldf库中,如果有人熟悉这些(他们导入/导出/添加整个表或表的子集到R数据表)。

为什么不给redis一个尝试?

您感兴趣的两个平台的驱动程序是可用的——python (redis, via package index]2)和R (rredis, CRAN)。

redis的天才之处在于不是它会神奇地识别NumPy数据类型,并允许你插入和提取多维NumPy数组,就像它们是本地redis数据类型一样,而是它的天才之处在于你可以用几行代码轻松地创建这样的接口。

有(至少)几个关于redis的python教程;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.]])

Doug对redis的建议非常好,但我认为他的代码有点复杂,因此相当慢。出于我的目的,我必须在不到十分之一秒的时间内序列化+写入,然后抓取+反序列化一个大约有一百万个浮点数的方阵,所以我这样做:

写作

:

snapshot = np.random.randn(1024,1024)
serialized = snapshot.tobytes()
rs.set('snapshot_key', serialized)

Then for reads:

s = rs.get('snapshot_key')
deserialized = np.frombuffer(s).astype(np.float32)
rank = np.sqrt(deserialized.size).astype(int)
snap = deserialized(rank, rank)

您可以使用%time对python进行一些基本的性能测试,但是tobytes或frombuffer都不会占用超过几毫秒的时间。

这看起来有点老,但有没有什么理由你不能做fetchall()而不是迭代,然后在声明时初始化numpy ?

我找到了至少三个Python包来连接SQLite和NumPy:

  • esutil。sqlite_util,它是esutil
  • 的一部分
  • hydroclimpy.io.sqlite
  • 我自己的RecSQL(可从github.com/orbeckst/RecSQL)

这些包都必须处理SQLite(默认情况下)只理解标准Python类型而不理解NumPy数据类型(如NumPy .int64)的问题。

RecSQL 0.7.8+适合我(大多数时候),但我认为它是一个相当糟糕的hack和浏览代码,esutil。Sqlite_util显得更加成熟

最新更新