在Python中复制SQL的“连接”

3 投票
2 回答
7596 浏览
提问于 2025-04-15 23:37

我正在尝试从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 上连接数组 r1r2

这个键应该是一个字符串,或者是一个字符串的序列,对应于用于连接数组的字段。如果在两个输入数组中找不到 key 字段,就会抛出异常。

key 上,r1r2 都不应该有重复值:如果有重复值,输出结果会变得非常不可靠。请注意,算法不会检查重复值。

来源: http://presbrey.mit.edu:1234/numpy.lib.recfunctions.html


任何建议或帮助都将非常感谢!

2 个回答

3

重新回到我之前问过的问题...

pandas这个库是个很好的解决方案。它提供了一种叫做“数据框”的东西,还有一种“合并”的方法。

6

假设你在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的连接条件(内连接、外连接、全连接)”),实际上没有其他选择,因为JOINON条件是相当灵活的。

对于外连接和全连接,你还需要保留一些信息,以识别哪些记录[[来自一个或两个表]]还没有被处理,并且需要处理——例如,对于左连接,你可以添加一个布尔值,在for r2的内部循环之前将其重置为yielded = False,如果yield执行了,就设置为True,在内部循环结束后,if not yielded:,就生成一个人工的连接记录(可能用None来表示缺失的v2值,因为没有r2可以用来填补这个空缺)。

要想获得显著的性能提升,你需要明确你愿意接受哪些关于on条件和表格的约束——从你的问题中我们已经知道,你不能对任一表的键施加unique约束,但还有很多其他的约束可能会有所帮助,而让我们去猜测在你的情况下哪些约束适用,实际上是没什么意义的。

撰写回答