【问题标题】:NumPy arrays with SQLite带有 SQLite 的 NumPy 数组
【发布时间】:2011-12-15 15:44:18
【问题描述】:

我在 Python 中看到的最常见的 SQLite 接口是sqlite3,但是有什么可以很好地与 NumPy 数组或recarrays 配合使用的吗?我的意思是一个识别数据类型并且不需要逐行插入并提取到 NumPy (rec)array 中的...?有点像 RDBsqldf 库中的 R 的 SQL 函数,如果有人熟悉的话(它们将整个表或表子集导入/导出/附加到 R 数据表或从 R 数据表中)。

【问题讨论】:

  • 我建议看看PyTables。它使用 HDF5 作为后端,而不是 SQLite,但还支持强大的查询。
  • 谢谢,但我希望它出现在 SQLite 中,以便 R 可以尝试一下(R 使用 SQL 表比使用 HDF5 文件做得更好)。

标签: python arrays sqlite numpy scipy


【解决方案1】:

为什么不试试redis

提供适用于您感兴趣的两个平台的驱动程序——python(redis,通过包索引]2)和 R(rredisCRAN) .

redis 的天才不是它会神奇地识别 NumPy 数据类型并允许您插入和提取多维 NumPy 数组,就好像它们是本机 redis 数据类型一样,而是它的天才在于只需几行代码即可轻松创建这样的界面。

python 中(至少)有几个关于 redis 的教程; DeGizmo blog上的那个特别好。

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.]])

【讨论】:

  • 这对于在程序之间交换数据/信息来说是一个好主意! - 也感谢这个例子。不幸的是,redis 是一种内存解决方案?而且我要交换的数据很大,所以能够使用硬盘文件是可取的......
  • 谢谢!这对我帮助很大!
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    我找到了至少三个 Python 包到interface SQLite and NumPy:

    这些包中的每一个都必须处理SQLite(默认情况下)只理解standard Python types而不理解NumPy data types的问题,例如numpy.int64。

    RecSQL 0.7.8+ 对我有用(大部分时间),但我认为这是一个非常糟糕的 hack 并且浏览代码,esutil.sqlite_util 似乎更成熟。

    【讨论】:

      【解决方案4】:

      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)
      

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

      【讨论】:

      • 很好的建议,但请注意np.frombuffer(s).astype(np.float32):这将解析缓冲区s,就好像它具有dtype np.float64,然后将其转换为np.float32。如果原始矩阵具有 dtype np.float32 这将返回一个大小为一半的矩阵。最好使用np.frombufferdtype 参数(即np.frombuffer(s, dtype=np.float32)
      • 很好,我在这里很草率,尤其是混入了python int。
      猜你喜欢
      • 1970-01-01
      • 2011-12-07
      • 2020-08-09
      • 2021-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多