【问题标题】:Numpy/Pandas: Merge two numpy arrays based on one array efficientlyNumpy/Pandas:基于一个数组高效合并两个numpy数组
【发布时间】:2021-07-13 18:30:49
【问题描述】:

我有两个由两组元组组成的 numpy 数组:

a = [(1, "alpha"), (2, 3), ...]
b = [(1, "zylo"), (1, "xen"), (2, "potato", ...]

元组中的第一个元素是标识符并在两个数组之间共享,所以我想创建一个新的numpy数组,如下所示:

[(1, "alpha", "zylo", "xen"), (2, 3, "potato"), etc...]

我目前的解决方案有效,但对我来说效率太低了。看起来像这样:

aggregate_collection = []
for tuple_set in a:
  for tuple_set2 in b:
    if tuple_set[0] == tuple_set2[0] and other_condition:
      temp_tup = (tuple_set[0], other tuple values)
      aggregate_collection.append(temp_tup)

我怎样才能有效地做到这一点?

【问题讨论】:

  • 我怀疑pandas.group_by 的答案只是隐藏了复杂性。你确定这些是numpy数组吗?它们看起来更像元组列表。这不是从numpy 中受益的任务
  • @hpaulj 这些是带有单个元组元素的 numpy 数组。
  • 我同意 pandas 看起来不是正确的方法。看起来 numpy 也不是正确的数据结构,因为您将多种类型混合在一起。我认为这个minimal reproducible example 并不代表实际问题:p

标签: python arrays pandas numpy


【解决方案1】:

我会将它们连接成一个数据框,然后只需 groupby+agg

(pd.concat([pd.DataFrame(a), pd.DataFrame(b)])
   .groupby(0)
   .agg(lambda s: [s.name, *s])[1])

其中01 是通过pd.DataFrame 创建数据框时给出的默认列名。将其更改为您的列名。

【讨论】:

  • 你能更深入地解释一下agg(lambda s: [s.name, *s])[1]吗?这也不符合我在双嵌套 for 循环中写的条件。
  • agg 将所有值聚合到一个列表中。 [s.name, *s] 表示此列表将第一个项目作为索引(在您的示例中为 1 和 2),其余项目在列表中(在您的示例中,"alpha", "zylo", "xen" 用于索引 1 和` 3, "potato"` 用于索引 2)。其他条件也将进入 groupby,但我不知道它们,并且很难预测结构会是什么样子。
  • 啊,好的。我正在比较两组时间并确保它们落在一个区间内,即a_time - b_time <= time_delta_interval。这适合group_by吗?
【解决方案2】:
In [278]: a = [(1, "alpha"), (2, 3)]
     ...: b = [(1, "zylo"), (1, "xen"), (2, "potato")]
In [279]: a
Out[279]: [(1, 'alpha'), (2, 3)]
In [280]: b
Out[280]: [(1, 'zylo'), (1, 'xen'), (2, 'potato')]

请注意,如果我尝试从 a 创建一个数组,我会得到完全不同的结果。

In [281]: np.array(a)
Out[281]: 
array([['1', 'alpha'],
       ['2', '3']], dtype='<U21')
In [282]: _.shape
Out[282]: (2, 2)

defaultdict 是一个方便的工具,用于收集相似键值

In [283]: from collections import defaultdict
In [284]: dd = defaultdict(list)
In [285]: for tup in a+b:
     ...:     k,v = tup
     ...:     dd[k].append(v)
     ...: 
In [286]: dd
Out[286]: defaultdict(list, {1: ['alpha', 'zylo', 'xen'], 2: [3, 'potato']})

可以转换为元组列表:

In [288]: [(k,*v) for k,v in dd.items()]
Out[288]: [(1, 'alpha', 'zylo', 'xen'), (2, 3, 'potato')]

我使用a+b 加入列表,因为显然元组出现在哪里并不重要。

Out[288] 甚至不适合 numpy,因为元组的大小不同,并且项目(第一个除外)可能是字符串或数字。

【讨论】:

    猜你喜欢
    • 2017-09-19
    • 1970-01-01
    • 1970-01-01
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多