1

I have a list that varies in size and I would like to copy it over a numpy array. I already have a way to do but I would like to see if there is a more elegant way.

Let's say I have the following:

import numpy as np
data = np.full((10,), np.nan)

# I want to copy my list into data starting at index 2
def apply_list(my_list):
    data[2:2+len(mylist)] = mylist

# Example
tmp = [1, 2, 3, 4]        # can vary from 2 to 8 elements
apply_list(tmp)

After this, I expect data to look like this:

[nan, nan, 1, 2, 3, 4, nan, nan, nan, nan]

Please keep in mind that len(mylist) can range from 2 to 8.

I am marking unused places with NaN and data has been preallocated and should always be size=10, regardless of the size of my_list. For that reason, simply appending will not work.

I particularly don't like much doing 2:2+len(mylist). Is there a nicer/cleaner way of doing this?

5
  • 3
    That's the simplest way to do the job. Commented May 12, 2017 at 18:11
  • Is there some way of combining this with some iterator/generator? (obviously without having to iterate in plain python). I know about np.fromiter but not sure how to connect that to the assignment Commented May 12, 2017 at 18:16
  • Are you looking for speed or pretty code? Commented May 12, 2017 at 18:17
  • well.. both :). I am learning more about numpy and I came up with this problem. If I can improve style, it would be great. But clearly I dont want to have a performance hit. Commented May 12, 2017 at 18:18
  • 1
    You case matches the 2nd example in this pararagraph: docs.scipy.org/doc/numpy/user/…, x[2:7] = np.arange(5). Assignment to a list works the same way - except that the RHS slot does not have match in size. Array size is fixed, list size is not. Commented May 12, 2017 at 18:22

1 Answer 1

2

I'm not aware of any numpy-function that could simplify this. However you could wrap it as function so the complexity is hidden:

def put(arr, subarr, startidx):
    arr[startidx:startidx+len(subarr)] = subarr
    return arr

or with sequential indexing (not recommended):

def put(arr, subarr, startidx):
    arr[startidx:][:len(subarr)] = subarr
    return arr

You could also pad your mylist with NaNs:

np.pad(np.array(mylist, dtype=float), 
       (2, 8-len(mylist)), 
       mode='constant', 
       constant_values=np.nan)
Sign up to request clarification or add additional context in comments.

3 Comments

sorry to ask about the "non recommended" one.. but it looks interesting. I never thought about it.. Why do not say is not recommended?
I think padding isn't really as performant, the other ones will be faster. I meant I wouldn't recommend the second approach becauseit just avoids the startidx+ by adding a not-so-readable double slicing operation.
np.pad is a complex function that does a lot of concatenates. And at the compiled code level, concatenate does the same sort of allocate and assign operation that the OP is trying to avoid.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.