0

I have an array x of 30 samples, and I wish to separate it out into chunks of 8 samples each in 2 different ways.

First, I want to separate it avoiding any overlap so that I end up with 3 arrays of length 8 and the final array will be only 6 (due to some samples being missing).

Secondly, I want to separate it so that the final array will be the last 2 samples of the previous array plus the final 6.

Both methods preferably without for loops as I'm trying to optimise this for when I expand it to arrays with lengths in the ten thousands.

I have tried using np.array_split as follows

x = np.array([1 ,1, 2 ,1 ,1 ,2 ,1, 0 ,3, 1, 2 ,2, 1, 2, 1, 1,50,1 ,1, 1, 1, 4, 1, 11, 15, 0, 0, 1, 1,0])

y = np.array_split(x,np.ceil(len(x)/8))

However, that results in:

y = [array([1, 1, 2, 1, 1, 2, 1, 0]),
 array([3, 1, 2, 2, 1, 2, 1, 1]),
 array([50,  1,  1,  1,  1,  4,  1]),
 array([11, 15,  0,  0,  1,  1,  0])]

so y is clearly made up of 2x8 length arrays and 2x7 length arrays, not what I want. How do I go about achieving it the way I want. The first method is the more important, the second is a bonus.

Thanks

Jack
  • 107
  • 7
  • if instead of a list of arrays you end up with a single 2D array, would that work for you? If so, then you can just reshape your initial array. – Sembei Norimaki Nov 24 '22 at 12:31
  • @SembeiNorimaki a 2D array is fine for what I need later on... not quite sure how that would work though with the inequalities in rows of the 2D array for reshaping, could you please explain further? – Jack Nov 24 '22 at 12:36
  • I've Updated 2 solutions @Jack . Pls, Try them & Let me know if any issues. – Bhargav - Retarded Skills Nov 24 '22 at 13:36
  • @Bhargav sorry I've been pulled into something else, I will go back and test your solutions asap, thank you – Jack Nov 24 '22 at 14:24
  • Hi @Bhargav sorry for not getting back to you sooner, I'm using a restricted laptop so am not able to install utilspie atm, but when I get back to my home computer, I will give it a try (but that won't be till later this week). Looking at your solution though I do think it will work – Jack Nov 28 '22 at 14:53
  • Ohhh...you only mentioned you preferably without loops....Never mentioned third party libraries are not allowed...Are you still trying to find solution?. If so i can provide alternative solution – Bhargav - Retarded Skills Nov 28 '22 at 15:30
  • @Bhargav yeah that's my bad sorry. I'm using harry's solution to problem 1, but a solution to problem 2 is still eluding me so if you could come up with one that would be extremely helpful – Jack Nov 28 '22 at 15:43

4 Answers4

1
import numpy as np

x = np.array([1 ,1, 2 ,1 ,1 ,2 ,1, 0 ,3, 1, 2 ,2, 1, 2, 1, 1,50 ,1 ,1, 1, 1, 4, 1, 11, 15, 0, 0, 1, 1,0])

def split_reminder(x, chunk_size, axis=0):
    indices = np.arange(chunk_size, x.shape[axis], chunk_size)
    return np.array_split(x, indices, axis)

split_reminder(x, 8)

Checkout the below link for reference: Similar answer

chrslg
  • 9,023
  • 5
  • 17
  • 31
harry_09
  • 11
  • 2
0
"""for the first you can use range"""
x = np.array([1 ,1, 2 ,1 ,1 ,2 ,1, 0 ,3, 1, 2 ,2, 1, 2, 1, 1,50,1 ,1, 1, 1, 4, 1, 11, 15, 0, 0, 1, 1,0])
res = [x[i:i+8] for i in range(0, len(x), 8)]
"""for the second you could just pop the first item"""
res.pop(0)
print(res)
Tat
  • 51
  • 4
  • hi @Tat thank you, I will try that. It does use a for loop so I would prefer a solution without them if you know of one – Jack Nov 24 '22 at 12:48
0

Use utilpsace

from utilspie import iterutils

x = np.array([1 ,1, 2 ,1 ,1 ,2 ,1, 0 ,3, 1, 2 ,2, 1, 2, 1, 1,50,1 ,1, 1, 1, 4, 1, 11, 15, 0, 0, 1, 1,0])

print(list(iterutils.get_chunks(x, 8)))

Gives

[array([1, 1, 2, 1, 1, 2, 1, 0]),  #Length 8
 array([3, 1, 2, 2, 1, 2, 1, 1]),  #Length 8
 array([50,  1,  1,  1,  1,  4,  1, 11]), #Length 8
 array([15,  0,  0,  1,  1,  0])]  #Length 6

Solution 2

Fill uneven array lengths with above array elements using bottleNeck

Complete code. ##

import numpy as np
from utilspie import iterutils
import itertools
from bottleneck import push

x = np.array([1 ,1, 2 ,1 ,1 ,2 ,1, 0 ,3, 1, 2 ,2, 1, 2, 1, 1,50,1 ,1, 1, 1, 4, 1, 11, 15, 0, 0, 1, 1,0])

x =(list(iterutils.get_chunks(x, 8)))

x_new=np.array(list(itertools.zip_longest(*x, fillvalue=np.nan))).T

x_new=push(x_new, axis=0)
print(x_new)

Gives #

[[ 1.  1.  2.  1.  1.  2.  1.  0.]  #Length 8
 [ 3.  1.  2.  2.  1.  2.  1.  1.]  #Length 8
 [50.  1.  1.  1.  1.  4.  1. 11.]  #Length 8
 [15.  0.  0.  1.  1.  0.  1. 11.]] #Length 8
0

You could split just the part of the array will produces your chunk size then add back on an array of the final 8 values

num = int(len(x)/8)
y = np.array_split(x[:num*8], num)
y += [x[-9:-1]]
user19077881
  • 3,643
  • 2
  • 3
  • 14