减少 ndarray 中的一维

reduce one dimension within an ndarray

我将点坐标存储在一个 3 维数组中:
(UPD。数组实际上是 numpy-derived ndarray,对于初始版本中的混淆感到抱歉)

a = [ [[11,12]], [[21,22]], [[31,32]], [[41,42]] ]

你看到每个坐标对都存储为嵌套二维数组,如 [[11,12]],而我希望它是 [11,12],即我的数组应包含以下内容:

b = [ [11,12], [21,22], [31,32], [41,42] ]

那么,如何从a变成b形式呢?现在我的解决方案是创建一个列表,然后使用 numpy:

将其转换为数组
b = numpy.array([p[0] for p in a])

这可行,但我认为必须有更简单、更清洁的方法...

更新。最初我试图做一个简单的理解:b = [p[0] for p in a] - 但后来 b 结果是一个列表,而不是数组 - 我假设这是因为原始 a 数组是 ndarray 来自 numpy

这是另一个使用列表理解的解决方案:

b = [x[0] for x in a]

如果你想使用 numpy:

b = np.array(a)[:, 0, :]

这比理解要快。


嗯...我当然认为会是

a = np.random.random((100_000, 1, 2)).tolist()

%timeit np.array([x[0] for x in a])
41.1 ms ± 304 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit np.array(a)[:, 0, :]
57.6 ms ± 1.27 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit x = np.array(a); x.shape = len(a), 2
58.2 ms ± 381 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

编辑

哦,如果它是一个 numpy 数组,那么一定要使用这个方法。或者如果您确定它不为空,请使用 .squeeze()

为了像你所说的那样压扁一个 "nested 2-d array like",你只需要得到第一个元素。 arr[0]

以多种方式应用此概念:

  • 列表理解(表现最好):flatter_a_compr = [e[0] for e in a]
  • 迭代(第二好的表现):

    b =[]
    for e in a:
        b.append(e[0])
    
  • lambda(非 Pythonic):flatter_a = list(map(lambda e : e[0], a))

  • numpy(表现最差):flatter_a_numpy = np.array(a)[:, 0, :]

如果你以后要用到numpy,那么最好避免list comprehension。此外,尽可能使事情自动化始终是一种好习惯,因此与其手动选择单例维度,不如让 numpy 来处理: b=numpy.array(a).squeeze() 除非你需要保留其他单例维度。