4

Question

I have an array: foo = [1,2,3,4,5,6,7,8,9,10]
And I was wondering the best way to get this array on the following shape:

[[ 1.,  2.,  3.],
 [ 4.,  5.,  6.],
 [ 7.,  8.,  9.],
 [10.]]

How should I do ?
Thanks!


What I currently do

Since foo doesn't contains multiple of 3 elements using numpy.reshape() gives an error

import numpy as np
np.reshape(foo,(-1,3))

ValueError: cannot reshape array of size 10 into shape (3)

So I need to force my array to contain multiple of 3 elements, either by dropping some (but I lose some data):

_foo = np.reshape(foo[:len(foo)-len(foo)%3],(-1,3))

print(_foo)
[[1 2 3]
 [4 5 6]
 [7 8 9]]

Or by extending with nan:

if len(foo)%3 != 0:
    foo.extend([np.nan]*((len(foo)%3)+1))

_foo = np.reshape(foo,(-1,3))
print(_foo)
[[ 1.  2.  3.]
 [ 4.  5.  6.]
 [ 7.  8.  9.]
 [10. nan nan]]

Notes

  • @cᴏʟᴅsᴘᴇᴇᴅ recommendation is rather to work with full arrays instead (padding with nan or 0 for instance)
jpp
  • 159,742
  • 34
  • 281
  • 339
David Leon
  • 1,017
  • 8
  • 25

1 Answers1

2

You can use @NedBatchelder's chunk generator (upvote there).

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

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

list(chunks(lst, 3))

# [[1, 2, 3],
#  [4, 5, 6],
#  [7, 8, 9],
#  [10]]
jpp
  • 159,742
  • 34
  • 281
  • 339
  • Note that this only works for lists, arrays, etc. that are indexable! If you want something that works for generators too, Jinja2's batch filter is adaptable to your uses. https://github.com/pallets/jinja/blob/master/jinja2/filters.py#L737-L765 – AKX Mar 07 '18 at 14:09