Vasily A
Vasily A

Reputation: 8626

reduce one dimension within an ndarray

I have points coordinates stored in a 3-dimensional array:
(UPD. the array is actually numpy-derived ndarray, sorry for the confusion in the initial version)

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

you see that each coordinate pair is stored as nested 2-d array like [[11,12]], while I would like it to be [11,12], i.e. my array should have this content:

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

So, how to get from a to b form? For now my solution is to create a list and then convert it to an array with numpy:

b = numpy.array([p[0] for p in a])

This works but I assume there must be a simpler and cleaner way...

UPD. originally I tried to do a simple comprehension: b = [p[0] for p in a] - but then b turned out to be a list, not an array - I assume that's because the original a array is ndarray from numpy

Upvotes: 1

Views: 934

Answers (4)

anishtain4
anishtain4

Reputation: 2402

If you are going to use numpy later, then it's best to avoid the list comprehension. Also it's always good practice to automate things as much as possible, so instead of manually selecting the singleton dimension just let numpy take care of: b=numpy.array(a).squeeze() Unless there are other singleton dimensions that you need to keep.

Upvotes: 2

FHTMitchell
FHTMitchell

Reputation: 12147

If you do want to use numpy:

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

This will be faster than a comprehension.


Well... I certainly thought it would be

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)

edit

Oh if its a numpy array then definitely use this method. Or use .squeeze() if you're sure it's not empty.

Upvotes: 3

Attersson
Attersson

Reputation: 4866

In order to flatten a "nested 2-d array like" as you call them, you just need to get the first element. arr[0]

Apply this concept in several ways:

  • list comprehension (most performing) : flatter_a_compr = [e[0] for e in a]
  • iterating (second best performing):

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

  • numpy (worst performing) : flatter_a_numpy = np.array(a)[:, 0, :]

Upvotes: 1

betontalpfa
betontalpfa

Reputation: 3742

Here is another solution using list comprehension:

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

Upvotes: 2

Related Questions