4

I have a vector of complex numbers (the result of a FFT) and I would like to scale only the real part of the complex numbers by factors in another vector.

Example

cplxarr= np.array([1+2j, 3+1j, 7-2j])
factarr= np.array([.5, .6, .2])
# desired result of cplxarr * factarr :
# np.array([.5+2j 1.8+1j 1.4-2j])

(Yes, it's about human-hearing frequency response in a very specific setting.)
Obviously the multiplication with the vectors as above scales the imaginary parts too.

How do I set up factarr and what operation do I have to do in order to achieve the desired result? If it's possible at all, that is, without separating the real and imaginary parts, scaling the real parts and reassembling as a new complex vector.

1 Answer 1

8

This'll do it:

>>> factarr*cplxarr.real + (1j)*cplxarr.imag
array([ 0.5+2.j,  1.8+1.j,  1.4-2.j])

Not sure if it's the best way though.


It turns out that for me at least (OS-X 10.5.8, python 2.7.3, numpy 1.6.2) This version is about twice as fast as the other version which uses np.vectorize:

>>> from timeit import timeit
>>> timeit('factarr*cplxarr.real+(1j)*cplxarr.imag',setup='from __main__ import factarr,cplxarr')
21.008132934570312
>>> timeit('f(cplxarr.real * factarr, cplxarr.imag)',setup='from __main__ import factarr,cplxarr; import numpy as np; f=np.vectorize(np.complex)')
46.52931499481201

It doesn't seem to make much of a difference between using np.complex and complex provided by python:

>>> timeit('f(cplxarr.real * factarr, cplxarr.imag)',setup='from __main__ import  factarr,cplxarr; import numpy as np; f=np.vectorize(complex)')
44.87726283073425

THE CURRENT LEADER IN THE TIMINGS STANDINGS (proposed by eryksun in the comments below)

>>> timeit.timeit('a = cplxarr.copy(); a.real *= factarr ',setup='from __main__ import factarr,cplxarr')
8.336654901504517

And proof that it works:

>>> a = cplxarr.copy()
>>> a.real *= factarr 
>>> a
array([ 0.5+2.j,  1.8+1.j,  1.4-2.j])

This obviously would be even faster if you wanted to do the operation in place (and could therefore leave the copy off).

Sign up to request clarification or add additional context in comments.

9 Comments

(+1) I prefer your version to mine.
@NPE -- I'd have to timeit before I come up with a preferred solution ;-)
Thank you; that is the disassembling/reassembling method, of course. I will not pick your answer for a little while, giving someone the chance to offer a different answer, if there is such a beast.
@tzot: Did you want this done in place? That's just cplxarr.real *= factarr. Otherwise, you could try a [:] copy followed by an in-place scale of the real component.
@eryksun -- I think that ndarray.copy is probably better for copying. [:] should return a view, not a copy when dealing with np.ndarrays. But just updating the real component in place is a good idea.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.