我正在尝试从R切换到Python(主要是围绕一般灵活性的问题)。使用Numpy,matplotlib和ipython,除了合并“数据集”之外,我还能够覆盖我的所有用例。我想纯粹在python中模拟SQL的join by子句(inner,outer,full)。 R使用'merge'函数处理它。
我已经尝试过numpy.lib.recfunctions join_by,但是关键是'key'重复出现问题:
join_by(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2',
defaults=None, usemask=True, asrecarray=False)
在关键r1
上加入数组r2
和key
。
键应该是字符串或对应的字符串序列
到用于加入数组的字段。
如果在两个输入中找不到key
字段,则会引发异常
阵列。
r1
和r2
都不应该在key
上有任何重复:
重复将使输出非常不可靠。请注意重复
没有被算法查找。
来源:http://presbrey.mit.edu:1234/numpy.lib.recfunctions.html
任何指针或帮助都将非常感激!
答案 0 :(得分:6)
假设您在Python中表示SQL表的等价物作为dicts列表,所有具有相同(假设字符串)键的字符串(其他表示形式,包括由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的连接子句(内部,外部,完整)“)实际上没有其他选择,因为ON
的{{1}}子句非常不受限制。
对于外部和完全连接,您还需要保留信息,以识别哪些记录[[来自一个或两个表]]尚未产生,否则产生 - 例如对于左连接,您需要添加bool,在JOIN
内循环之前重置为yielded = False
,如果执行for r2
则设置为True
,在内循环之后, yield
,生成一个人工连接记录(可能使用if not yielded:
代替NULL代替缺少的None
值,因为没有v2
实际用于此目的)
为了获得显着的效率提升,您需要澄清您对r2
谓词和表格所依据的约束条件 - 我们已经从您的问题中了解到您无法忍受on
约束任何一个表的键,但还有许多其他约束可能有帮助,并且让我们猜测在你的情况下实际应用这些约束将是一个非常无益的努力。
答案 1 :(得分:3)
重新回答这个问题,我最初问过......
pandas库是一个完美的解决方案。它提供“数据帧”类和“合并”技术。