复制SQL';s';加入';用Python

复制SQL';s';加入';用Python,python,numpy,Python,Numpy,我正在尝试从R转换到Python(主要是关于一般灵活性的问题)。有了Numpy、matplotlib和ipython,我能够涵盖我所有的用例,除了合并“数据集”。我想纯粹用python模拟SQL的join by子句(内部、外部、完整)。R使用“merge”函数处理这个问题 我已经尝试了numpy.lib.recfunctions join_by,但它在“键”上出现了重复的问题: 在键上连接数组r1和r2 键应该是一个字符串或对应的字符串序列 添加到用于加入数组的字段。 如果在两个输入中找不到键

我正在尝试从R转换到Python(主要是关于一般灵活性的问题)。有了Numpy、matplotlib和ipython,我能够涵盖我所有的用例,除了合并“数据集”。我想纯粹用python模拟SQL的join by子句(内部、外部、完整)。R使用“merge”函数处理这个问题

我已经尝试了numpy.lib.recfunctions join_by,但它在“键”上出现了重复的问题:


在键
上连接数组
r1
r2

键应该是一个字符串或对应的字符串序列 添加到用于加入数组的字段。 如果在两个输入中找不到
字段,则会引发异常 数组

无论是
r1
还是
r2
都不应该在
键上有任何重复项:存在
大量重复会使输出非常不可靠。请注意,重复的
算法未查找到的

资料来源:



任何指点或帮助都将不胜感激

假设您在Python中将SQL表的等价物表示为DICT列表,所有DICT都具有相同的(假定字符串)键(其他表示,包括通过
numpy
启用的表示,可以在逻辑上归结为等价形式)。现在,内部联接(同样,从逻辑的角度来看)是笛卡尔积的投影——在一般情况下,在
上取一个谓词参数
(它从每个表中取两个参数,一个“记录”[[dict]],如果需要联接两个记录,则返回一个真值),简单的方法是(使用每表前缀消除歧义,以避免两个表可能具有相同的“字段”):

现在,您当然不想这样做,因为性能是
O(M*N)
——但是,对于您指定的一般性(“模拟SQL的join by子句(内部、外部、完整)”),实际上没有其他选择,因为
join
ON
子句非常不受限制

对于外部联接和完全联接,您还需要保留标识哪些记录[[来自一个或两个表]]的信息尚未生成,否则将生成-例如,对于左连接,您将在r2
内循环的
之前重置为
生成=False
,如果执行
生成
,则将其设置为
,在内循环之后,如果未生成:
,则生成一个人工连接的记录(假定使用
None
表示空值,以代替缺少的
v2
值,因为没有真正用于此目的的
r2


为了获得任何实质性的效率改进,您需要澄清关于
谓词和表上的
您愿意遵守的约束条件——从您的问题中我们已经知道,您不能接受任何一个表的键上的
唯一的
约束,但还有许多其他约束条件可能存在帮助,让我们猜测这些约束在您的案例中实际应用的是什么,这将是一个相当徒劳无益的尝试。

重温我最初问的这个问题


该库是一个完美的解决方案。它提供了一个“数据帧”类和一个“合并”技术。

Hmm…如果您提供一个简短的代码示例来说明您想做什么,我会更容易理解这一点。谢谢您,上面的内容非常有趣。而且非常有用。主要用例和核心约束是“内部”join在两个数据集上。多个数据集可以连续使用。非约束是记录的连接后顺序。因此,对数据进行排序并使用b树进行性能测试是非常好的。我“相对”确定我可以自己编写代码,但在我开始这条路之前,我想确保我没有遗漏一些预先制作的内容。PS,我还尝试了d结果=[r1+r2,对于t1中的r1,对于t2中的r2,如果r1[0]==r2[1]]但是缺少列名使它变得混乱。而且性能很差。@danmat,在这两行之间的某个地方,您似乎相信或想当然地认为,
on
条件的唯一可能形式是第一个表的一列和第二个表的一列之间相等——您是否介意正确地阅读您的内容?因为SQL与此相去甚远(
on
可以是SQL中的任何谓词!),因此我怀疑我的水晶球可能有点模糊,因为您提到了“在Python中复制SQL连接”作为你的Q的标题。如果我的水晶球恰好是正确的,有几种方法来优化这个超级特例!谢谢。我会深入挖掘来优化我的用例。@丹麦,考虑将每个表预处理成一个DICT,将相关键的值映射到具有该值的行集合(或其索引等)。--以排序键“同步”的顺序在这两个dict上行走(典型的“合并排序列表”)为您提供了一种执行任何类型联接的性能良好的方法。您可以使用辅助DICT来执行此操作,只对已排序的表进行排序,但仅对DICT键进行排序可能比对整个表进行排序更快。更新此线程。我通过使用python中的嵌入式SQLite数据库找到了一个优雅的解决方案。
join_by(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2',
        defaults=None, usemask=True, asrecarray=False)
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