在Python中复制SQL的“连接”
我正在尝试从R语言转到Python,主要是因为Python在灵活性方面更好。使用Numpy、matplotlib和ipython后,我几乎可以满足所有需求,除了合并“数据集”这一块。我想在Python中模拟SQL的连接操作(包括内连接、外连接和全连接)。在R中,这个功能是通过“merge”函数来实现的。
我尝试过使用numpy.lib.recfunctions中的join_by,但在处理重复的“键”时出现了严重问题:
join_by(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2',
defaults=None, usemask=True, asrecarray=False)
在键 key
上连接数组 r1
和 r2
。
这个键应该是一个字符串,或者是一个字符串的序列,对应于用于连接数组的字段。如果在两个输入数组中找不到 key
字段,就会抛出异常。
在 key
上,r1
和 r2
都不应该有重复值:如果有重复值,输出结果会变得非常不可靠。请注意,算法不会检查重复值。
来源: http://presbrey.mit.edu:1234/numpy.lib.recfunctions.html
任何建议或帮助都将非常感谢!
2 个回答
重新回到我之前问过的问题...
pandas这个库是个很好的解决方案。它提供了一种叫做“数据框”的东西,还有一种“合并”的方法。
假设你在Python中用一个字典的列表来表示一个SQL表格,所有的字典都有相同的(假设是字符串类型的)键(其他的表示方式,比如用numpy
,也可以归结为类似的形式)。那么,内连接从逻辑上来说,就是它们的笛卡尔积的一个投影——一般情况下,内连接需要一个on
参数(这个参数需要两个输入,一个是来自每个表的“记录”[[dict]],如果这两条记录需要连接,就返回真)。一个简单的方法是(使用每个表的前缀来避免混淆,因为两个表可能有同名的“字段”):
def inner_join(tab1, tab2, prefix1, prefix2, on):
for r1 in tab1:
for r2 in tab2:
if on(r1, r2):
row = dict((prefix1 + k1, v1) for k1, v1 in r1.items())
row.update((prefix2 + k2, v2) for k2, v2 in r2.items())
yield row
当然,你不想这样做,因为性能是O(M * N)
——但为了你所说的通用性(“模拟SQL的连接条件(内连接、外连接、全连接)”),实际上没有其他选择,因为JOIN
的ON
条件是相当灵活的。
对于外连接和全连接,你还需要保留一些信息,以识别哪些记录[[来自一个或两个表]]还没有被处理,并且需要处理——例如,对于左连接,你可以添加一个布尔值,在for r2
的内部循环之前将其重置为yielded = False
,如果yield
执行了,就设置为True
,在内部循环结束后,if not yielded:
,就生成一个人工的连接记录(可能用None
来表示缺失的v2
值,因为没有r2
可以用来填补这个空缺)。
要想获得显著的性能提升,你需要明确你愿意接受哪些关于on
条件和表格的约束——从你的问题中我们已经知道,你不能对任一表的键施加unique
约束,但还有很多其他的约束可能会有所帮助,而让我们去猜测在你的情况下哪些约束适用,实际上是没什么意义的。