如何在Python中从两个n维数组中获取匹配的行?

3
我有两个numPy数组,它们的行数不同但列数相同。每个数组的结构-年份,月份,日期,时间,卫星数量,数据值。每个数组都有不同类型的数据。
如何比较这两个数组以仅获取两个数组中共有的行,其中比较参数是前5列,然后是两个带有相应值的列。例如:
A=[('2015', '1', '1', 0.0, 'G06', 46.29)
 ('2015', '1', '1', 0.0, 'G12', 444.344)
 ('2015', '1', '1', 0.0, 'G14', -99.269)
 ('2015', '1', '1', 0.0, 'G20', 6.874)
 ('2015', '1', '1', 0.0, 'G24', 158.488)
 ('2015', '1', '1', 0.0, 'G25', -60.831)
 ('2015', '1', '1', 0.0, 'G31', -48.234)
 ('2015', '1', '1', 0.0, 'R07', -6.243)]

B=[('2015', '1', '1', 0.0, 'G06', '0.000')
 ('2015', '1', '1', 0.0, 'G12', '0.000')
 ('2015', '1', '1', 0.0, 'G14', '0.000')
 ('2015', '1', '1', 0.0, 'G24', '0.000')
 ('2015', '1', '1', 0.0, 'G25', '0.000')
 ('2015', '1', '1', 0.0, 'G29', '0.000')
 ('2015', '1', '1', 0.0, 'G31', '0.000')]

The result, I would like to get:

C=[('2015', '1', '1', 0.0, 'G06', 46.29, '0.000')
 ('2015', '1', '1', 0.0, 'G12', 444.344, '0.000')
 ('2015', '1', '1', 0.0, 'G14', -99.269, '0.000')
 ('2015', '1', '1', 0.0, 'G24', 158.488, '0.000')
 ('2015', '1', '1', 0.0, 'G25', -60.831, '0.000')
 ('2015', '1', '1', 0.0, 'G31', -48.234, '0.000')]

我可以使用循环来完成,但是当你有50000+行的数组时,这不是一个高效的解决方案。


你是否一定要使用numpy?当你处理带标签的表格数据时,这实际上是一个pandas问题。 - DSM
你的数组是一维结构化的,而不是n维的。你如何在循环中实现这个? - hpaulj
你能对顺序或唯一性做出任何假设吗? - hpaulj
谢谢大家的回答!@hpaulj 我正在使用“if”进行双重循环,寻找相同的行。它可以工作,但是像我写的那样需要太多时间 :) 我不太理解你关于顺序的问题。我尝试使用这里展示的解决方案 :) 再次非常感谢你们的帮助 :) - Olaniag
2个回答

3
在numpy代码的一个角落里,有一个简单的解决方案:recfunctions.join_by。
import numpy as np

A=[('2015', '1', '1', 0.0, 'G06', 46.29),
 ('2015', '1', '1', 0.0, 'G12', 444.344),
 ('2015', '1', '1', 0.0, 'G14', -99.269),
 ('2015', '1', '1', 0.0, 'G20', 6.874),
 ('2015', '1', '1', 0.0, 'G24', 158.488),
 ('2015', '1', '1', 0.0, 'G25', -60.831),
 ('2015', '1', '1', 0.0, 'G31', -48.234),
 ('2015', '1', '1', 0.0, 'R07', -6.243)]

B=[('2015', '1', '1', 0.0, 'G06', '0.000'),
 ('2015', '1', '1', 0.0, 'G12', '0.000'),
 ('2015', '1', '1', 0.0, 'G14', '0.000'),
 ('2015', '1', '1', 0.0, 'G24', '0.000'),
 ('2015', '1', '1', 0.0, 'G25', '0.000'),
 ('2015', '1', '1', 0.0, 'G29', '0.000'),
 ('2015', '1', '1', 0.0, 'G31', '0.000')]

dt=[('a', 'S4'), ('b', 'S1'), ('c', 'S1'), ('d',float), ('e', 'S3'), ('f',float)]
aA=np.array(A,dt)
aB=np.array(B,dt)

flds=list('abcde')

from numpy.lib import recfunctions
mrgd = recfunctions.join_by(flds, aA, aB, usemask=False)
print(mrgd)
print(mrgd.dtype)

生产
[('2015', '1', '1', 0.0, 'G06', 46.29, 0.0)
 ('2015', '1', '1', 0.0, 'G12', 444.344, 0.0)
 ('2015', '1', '1', 0.0, 'G14', -99.269, 0.0)
 ('2015', '1', '1', 0.0, 'G24', 158.488, 0.0)
 ('2015', '1', '1', 0.0, 'G25', -60.831, 0.0)
 ('2015', '1', '1', 0.0, 'G31', -48.234, 0.0)]
[('a', 'S4'), ('b', 'S1'), ('c', 'S1'), ('d', '<f8'), ('e', 'S3'), ('f1', '<f8'), ('f2', '<f8')]

在当前的组织中,必须单独导入recfunctionshttps://stackoverflow.com/a/33680606/901925

我们需要检查代码以了解其实际实现方式。而且,如果没有进一步的时间测试,我不知道速度如何与等效的pandas相比。


使用这个小样本,recfunctionspandas 更快,特别是如果包括创建数据框所需的时间。
In [302]: %%timeit 
   .....: a = pd.DataFrame(A)
   .....: b = pd.DataFrame(B)
   .....: c = pd.merge(a, b, 'inner', left_on=[0,1,2,3,4], right_on=[0,1,2,3,4]) 
   .....: 
100 loops, best of 3: 8.01 ms per loop
In [303]: %%timeit
   .....: aA=np.array(A,dt)
   .....: aB=np.array(B,dt)
   .....: aC=recfunctions.join_by(flds, aA, aB,usemask=False)
   .....: 
100 loops, best of 3: 3.35 ms per loop

与numpy的集合操作(如不尝试合并的in1d)相比,两者都较慢:

In [308]: timeit np.intersect1d(aA[flds],aB[flds])
1000 loops, best of 3: 326 µs per loop

2
使用pandas进行此操作:
import pandas as pd
a = pd.DataFrame(A)
b = pd.DataFrame(B)
c = pd.merge(a, b, 'inner', left_on=[0,1,2,3,4], right_on=[0,1,2,3,4])

其中'inner'表示仅在两个数组中都存在相同键值时才合并。而left_on=[0,1,2,3,4]表示使用这些列作为键值。

它会产生以下结果:

In: print(c)
Out: 
      0  1  2  3    4      5_x    5_y
0  2015  1  1  0  G06   46.290  0.000
1  2015  1  1  0  G12  444.344  0.000
2  2015  1  1  0  G14  -99.269  0.000
3  2015  1  1  0  G24  158.488  0.000
4  2015  1  1  0  G25  -60.831  0.000
5  2015  1  1  0  G31  -48.234  0.000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接