【发布时间】:2016-12-12 09:19:36
【问题描述】:
在我的程序中,我需要通过元数据进行查询。
我从类似 csv 的文本文件**将数据读入 numpy 记录数组 A,没有重复行**。
var1|var2|var3|var4|var5|var6
'a1'|'b1'|'c1'|1.2|2.2|3.4
'a1'|'b1'|'c4'|3.2|6.2|3.2
'a2'|''|'c1'|1.4|5.7|3.8
'a2'|'b1'|'c2'|1.2|2.2|3.4
'a3'|''|'c2'|1.2|2.2|3.4
'a1'|'b2'|'c4'|7.2|6.2|3.2
...
有百万行,嵌套循环中的查询可能高达十亿次(大部分匹配前3列),因此效率变得至关重要。 有 3 种类型的查询,第一种是最常见的。
-
获取与前 3 列中的一个或多个与给定字符串匹配的行,例如,
-
要匹配
var1='a2'和var2='b1'的记录,ind = np.logical_and(A['var1']=='a2', A['var2']=='b1') -
匹配
var1='a2'、var2='b1'和var3='c1'的记录,ind = np.logical_and(np.logical_and(A['var1']=='a2', A['var2']=='b1'), A['var3']=='c1')
-
正如我们所看到的,每次我们将列的所有元素与给定的字符串进行比较。
我认为映射可能是一种更有效的索引方式,因此我将 recarray A 转换为 dict D = {'var1_var2_var3: [var4, var5, var6], ...}, and search through the keys byfnmatch(keys, pat )`。我不确定这是不是更好的方法。
或者我可以创建一个分层字典 {'var1':{'var2':{'var3':[],...},...},...} 或内存 hdf5 /var1/var2/var3 并尝试获取该项目(如果存在)。这看起来是最快的方法?
后两种查询不是很频繁,我可以接受numpy recarray比较的方式。
-
获取特定范围内后一列中数值的所有行,例如,
-
获取 '1 所在的行
ind = np.logical_and(1<A['var4']<3), 0<A['var5']<3)
-
-
以上两者的组合,例如,
-
获取
var2='b1', '1 所在的行ind = np.logical_and(np.logical_and(A['var2']=='b1', 1<A['var4']<3), 0<A['var5']<3)
-
SQL 可能是一个好方法,但是对于这个小任务使用数据库看起来太重了。而且我无权在任何地方安装数据库支持。
对于快速内存查询的数据结构有什么建议吗? (如果很难有一个简单的自定义实现,sqlite 和 pandas.dateframe 似乎是可能的解决方案,正如建议的那样。)
【问题讨论】:
-
解释你对
numpy效率的担忧更多?至于数据库解决方案,sqlite3可以在内存中使用。 -
@hpaulj 每个查询都需要将数百万个项目与给定值进行比较,这看起来很浪费。我曾经尝试使用
dict,但似乎正则表达式匹配并不快。如果为此目的很难有一个简单的自定义 python 代码,sqlite和pandas.dateframe似乎是可能的解决方案。 -
在
numpy中,双边测试必须写成(1<A['var4'])&(A['var4']<3)
标签: python database numpy indexing mapping