1

I want to merge two arrays in python based on the first element in each column of each array.

For example,

A = ([[1, 2, 3],
[4, 5, 6],
[4, 6, 7],
[5, 7, 8], 
[5, 9, 1]])

B = ([[1, .002],
[4, .005],
[5, .006]])

So that I get an array

C = ([[1, 2, 3, .002],
[4, 5, 6, .005],
[4, 6, 7, .005],
[5, 7, 8, .006],
[5, 9, 1, .006]])

For more clarity:

First column in A is 1, 4, 4, 5, 5 and First column of B is 1, 4, 5

So that 1 in A matches up with 1 in B and gets .002

How would I do this in python? Any suggestions would be great.

4

5 回答 5

1

A原地修改可以吗?:

d = dict((x[0],x[1:]) for x in B)

现在d是一个字典,其中第一列是键,后续列是值。

for lst in A:
    if lst[0] in d: #Is the first value something that we can extend?
        lst.extend(d[lst[0]])

print A

做它不合适(受Ashwini回答的启发):

d = dict((x[0],x[1:]) for x in B)
C = [lst + d.get(lst[0],[]) for lst in A]

但是,使用这种方法,您需要在 A 和 B 中都有列表。如果您有一些列表和一些元组,它将失败(尽管如果需要,它可以解决),但它会使代码稍微复杂化。

使用这些答案中的任何一个,B都可以有任意数量的列

作为风格的旁注:我会将列表写为:

A = [[1, 2, 3],
     [4, 5, 6],
     [4, 6, 7],
     [5, 7, 8], 
     [5, 9, 1]]

我把括号去掉的地方......他们让它看起来太像你把一个列表放在tuple. Python 的自动续行发生在圆括号()、方括号[]或大括号{}中。

于 2013-01-10T21:51:47.917 回答
0

这是一个解决方案,使用itertools.product()它可以避免为 B 创建字典:

In [1]: from itertools import product

In [2]: [lst_a + lst_b[1:] for (lst_a, lst_b) in product(A, B) if lst_a[0] == lst_b[0]]
Out[2]:
[[1, 2, 3, 0.002],
 [4, 5, 6, 0.005],
 [4, 6, 7, 0.005],
 [5, 7, 8, 0.006],
 [5, 9, 1, 0.006]]
于 2013-01-11T01:45:31.970 回答
0

(这个答案假设这些只是常规列表。如果它们是 NumPy 数组,你有更多选择。)

看起来您想使用 B 作为查找表来查找要添加到 A 的每一行的值。

我将从 B 中的数据制作字典开始。碰巧的是,B 已经以正确的形式传递给dict()内置函数:

B_dict = dict(B)

然后你只需要逐行构建C。

对于 A 中的每一行,row[0]第一个元素是第一个元素,因此B_dict[row[0]]要添加到行尾的值也是。因此row + [B_dict[row[0]]是您要添加到 C 中的行。

这是一个从 A 和 B_dict 构建 C 的列表推导。

C = [row + [B_dict[row[0]]] for row in A]
于 2013-01-10T21:47:50.260 回答
0

您可以转换Bdictionary第一个,每个子列表的第一个元素作为键,第二个作为值。

然后简单地迭代A并附加从字典中获取的相关值。

In [114]: A = ([1, 2, 3],
[4, 5, 6],
[4, 6, 7],
[5, 7, 8], 
[6, 9, 1])

In [115]: B = ([1, .002],
[4, .005],
[5, .006])

In [116]: [x + [dic[x[0]]] if x[0] in dic else []  for x in A]
Out[116]: 
[[1, 2, 3, 0.002],
 [4, 5, 6, 0.005],
 [4, 6, 7, 0.005],
 [5, 7, 8, 0.006],
 [6, 9, 1]]
于 2013-01-10T21:53:19.970 回答
0

天真的,简单的方法:

for alist in A:
    for blist in B:
        if blist[0] == alist[0]:
            alist.extend(blist[1:])
            # alist.append(blist[1]) if B will only ever contain 2-tuples.
            break  # Remove this if you want to append more than one.

这里的缺点是它的复杂度为 O(N^2)。对于大多数小型数据集,这应该没问题。如果您正在寻找更全面的东西,您可能需要查看@mgilson 的答案。一些比较:

  1. 他的响应将所有内容转换B为 dict 并对每个元素执行列表切片。如果您在 中有很多值B,那可能会很昂贵。这使用现有列表(无论如何,您只查看第一个值)。
  2. 因为他使用的是 dicts,所以他的查找时间为 O(1)(他的回答还假设您永远不会将多个值附加到 中的值的末尾A)。这意味着总体而言,他的算法将达到 O(N)。您需要权衡创建 dict 的开销是否会超过B.
于 2013-01-11T02:04:42.483 回答