2

what is the faster way of copying from an array into a matrix. Example:

A = np.zeros((5, 3))
B = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

After copying values of B into A the resulting A should be:

[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [ 0  0  0]
 [ 0  0  0]]

Thank you in advance

mimou
  • 59
  • 5
  • @OzanDeniz thank you for the link but in my case I'm using two arrays with different shapes so no one of the three solutions could solve my problem – mimou Mar 10 '15 at 17:12

1 Answers1

6

You could use np.put:

In [74]: np.put(A, np.arange(len(B)), B)

In [75]: A
Out[75]: 
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.],
       [ 7.,  8.,  9.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

or assign to A.flat:

A.flat[:len(B)] = B

or (as ali_m points out) if A is C-contiguous, you could use A.ravel:

assert A.flags['C_CONTIGUOUS']
A.ravel()[:len(B)] = B

If A is not C-contiguous, then A.ravel() returns a copy. Modifying the copy does not modify A. Examples of non-C-contiguous arrays include slices with non-unit step size such as A[::2] and F-contiguous arrays such as np.asarray(A, order='F').


You can use Python's timeit module to benchmark pieces of code. If you have IPython, a particularly convenient way to benchmark code snippets is to use its %timeit "magic" function:

In [83]: A = np.zeros((500, 300))

In [84]: B = np.tile(np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]),1000)

In [88]: %timeit A = np.zeros((500, 300)); A.flat[:len(B)] = B
10000 loops, best of 3: 158 µs per loop

In [89]: %timeit A = np.zeros((500, 300)); np.put(A, np.arange(len(B)), B)
1000 loops, best of 3: 238 µs per loop

In [18]: %timeit A = np.zeros((500, 300)); A.ravel()[:len(B)] = B
10000 loops, best of 3: 91.6 µs per loop

which suggests that A.ravel()[:len(B)] = B is the faster than A.flat[:len(B)] = B which is faster than np.put(A, np.arange(len(B)), B).

Benchmarks can vary from machine to machine depending on many factors such as hardware, OS, version of software, or how the software was compiled. One piece of code could be faster than an alternative piece of code for small arrays but slower for larger arrays. So when you really want to benchmark, be sure to test the code on input, hardware and software closest to your actual use case, while keeping in mind the futility of pre-optimization.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • thank you very much it should be the solution but do you know which one is faster? – mimou Mar 10 '15 at 17:15
  • `A.ravel()[:len(B)] = B` is about 7x faster than `A.flat[:len(B)] = B` on my machine – ali_m Mar 11 '15 at 00:58
  • 1
    @ali_m: The problem with `ravel` is that in some circumstances it returns a copy rather than a view. When it returns a copy, modification of the copy does not affect `A`. For example, let `C = np.zeros((500, 300))` then define `A = C[::2]`. Then `A.ravel()[:len(B)] = B` does not modify `A`. – unutbu Mar 11 '15 at 09:37
  • Fair point, although since the OP was asking for a fast method, I still think `ravel` is worth mentioning for the common case where `A` is a C-contiguous array – ali_m Mar 11 '15 at 10:30
  • @ali_m: Good point. I've edited the post to include `ravel`. Thanks very much. – unutbu Mar 11 '15 at 11:21
  • Thank you guys! This solution solved my problem. In my case ravel and flat performed both nearly the same (55 seconds). But thank you @ali_m anyway! It's good to learn something new :) – mimou Mar 12 '15 at 18:28