【问题标题】:Filter a numpy array if any list within it contains at least one value of a previous row如果其中的任何列表包含前一行的至少一个值,则过滤 numpy 数组
【发布时间】:2017-08-23 13:29:46
【问题描述】:

我有一个 numpy 数组

b = np.array([[1,2], [3,4], [1,6], [7,2], [3,9], [7,10]])

现在,我想做以下事情:我想减少 b。我想减少它的方法是查看 b 的第一个元素,即 [1,2] 并基于此,我删除 b 中至少包含 12 的所有元素。在这种情况下,我将消除[1,6][7,2]。然后我会查看[3,4] 并消除那些至少包含34 的元素。

实际上,我从列表的开头开始,对于每个元素,我删除包含其中一个元素的其他元素。

我的尝试

for a in b:
    np.insert(b[~np.array([np.any((a==b)[j]) for j in range(len(b))])], 0,a, axis = 0)

遗憾的是,这不起作用!

这是我尝试过的,但它不起作用而且太长了。还有其他想法吗?

编辑 我认为主要问题是,当我执行np.any((a==b)[j]) 时,它只对那些第一个元素等于 a 的第一个元素的元素说 True,但当它们等于第二个元素时不说 True

编辑 2 你认为这会奏效吗?

for index, a in enumerate(b):
    np.insert(b[~np.array([np.any(np.logical_or(a[0]==b, a[1]==b)[j]) for j in range(len(b))])], index, a,  axis = 0)

【问题讨论】:

  • 嗯是的,但是删除它们的顺序很重要!想象一下,行的索引是某种排名。您希望只保留那些具有唯一数字的子数组,以便您拥有最高(即最低)排名
  • 最后结果应该是b = np.array([[1,2], [3,4], [7,10]])。如您所见,[1,2][1,6][7,2] 上幸存下来,[3,4][3,9] 上幸存下来,但是[7,2][7,10] 上幸存下来,因为[7,2][1,2] 淘汰了
  • 实际数据集的数组形状是什么?
  • 我还没有,但基本上这个列表将是以下结果:给定一个数字(比如 60k),我想创建它之前的所有数字组合(即 [ 0,0]、[1,1]、[1,59k] 等)
  • 那我想做其他的事情,但这就是大数字的由来

标签: python arrays numpy


【解决方案1】:

一个简单的解决方案是使用普通的 Python 循环:

b = np.array([[1,2], [3,4], [1,6], [7,2], [3,9], [7,10]])

final = []
seen = set()
for row in b.tolist():
    if seen.intersection(row):  # check if one element of the row has already been seen.
        continue
    else:
        # No item has been seen, so append this row and add the contents to the seen set.
        seen.update(row)
        final.append(row)

print(final)
# [[1, 2], [3, 4], [7, 10]]

我不确定是否有一个很好的 NumPy 函数来解决这类问题,但使用纯 Python 应该已经相当快了。

【讨论】:

  • 你认为 10^12 个元素的列表也会很快吗?
  • 我的意思是,比较快
  • 我怀疑你甚至可以制作一个包含 10^12 个元素的 numpy 数组,因为这需要大约 1000 GB 的内存!您可能需要查看一些可以将部分缓存到磁盘的数组类型。
  • 这可能比使用 numpy 数组更快,因为您不知道输出的长度。在 numpy 中追加发生在线性时间 iirc 中。另见stackoverflow.com/questions/10121926/…
  • 真的有 10**12 个元素吗?那是巨大的。这不适合任何普通 RAM,因为即使是由 int64 组成的 NumPy 数组也需要 8 TB。一个 Python 整数列表大约需要 35TB。
【解决方案2】:

根据数据的维度,您可能想要做一些不同的事情,但我一般来说解决这个问题的好方法是通过索引。 将 numpy 导入为 np

# Generate the data to work with
X = np.array([[1,2], [3,4], [1,6], [7,2], [3,9], [7,10]])

# Get the truth value is first value in the OR second value in the column
eq_idxs = np.logical_or(X == X[0, 0], X == X[0, 1])

# compress axis
eq_idxs = np.any(eq_idxs, axis=1)

#negate to get the remaining indexes
neq_idxs = np.logical_not(eq_idxs)

#Get the results
new_X = X[neq_idxs, :]
deleted_rows = X[eq_idxs, :]

print new_X 

输出:

[[ 3  4]
 [ 3  9]
 [ 7 10]]

如果你想重复把它换成一个while(X.shape[0] > 0):

【讨论】:

  • 它对你有用吗?当我运行您的示例时,我会收到 IndexError
  • 嗯,它现在给出了错误的结果 X = np.array([[1,2], [3,4], [1,6], [7,2], [3,9], [7,10]]) new_Xarray([[ 7, 10]])
  • 现在 100% 工作。
【解决方案3】:

只是添加一个依赖布尔索引和(可能太多)重塑和展平的 NumPy 答案。

import numpy as np
b = np.array([[1,2], [3,4], [1,6], [7,2], [3,9], [7,10]])

# flatten it for comparisons
b = b.ravel()
idx = 0
while idx < len(b) // 2:
    row = b[idx:idx+2]
    mask = np.zeros(b.shape, dtype=bool)
    np.logical_or(b[idx+2:] == row[0], b[idx+2:] == row[1], out=mask[idx+2:])
    b = b.reshape(-1, 2)  # reshape so "row" masking can be applied easily
    mask = mask.reshape(-1, 2).any(-1)
    b = b[~mask].ravel()  # ravel again after masking
    idx += 1
print(b.reshape(-1, 2))
# array([[ 1,  2],
#        [ 3,  4],
#        [ 7, 10]])

也许这可以使用np.isin 或类似方法进一步改进,但我没有时间(现在)进一步改进。

【讨论】:

    【解决方案4】:

    我想我找到了一种方法(几乎已经在我的编辑中),我会在这里发布它只是为了将来,我认为它类似于一些答案:

    for index, a in enumerate(b):
        if index >= len(b) - 1:
            break
        else:
            b  = np.insert(b[~np.array([np.any(np.logical_or(a[0]==b, a[1]==b)[j]) for j in range(len(b))])], index, a,axis=0)
    

    这应该可以工作

    【讨论】:

      猜你喜欢
      • 2020-04-08
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      • 2019-03-17
      • 1970-01-01
      • 2017-09-18
      • 2010-10-29
      • 1970-01-01
      相关资源
      最近更新 更多