combining real and imag columns in dataframe into complex number to obtain magnitude using np.abs

不羁岁月 提交于 2021-01-28 05:56:21

问题


I have a data frame that has complex numbers split into a real and an imaginary column. I want to add a column (2, actually, one for each channel) to the dataframe that computes the log magnitude:

 `    ch1_real  ch1_imag  ch2_real  ch2_imag  ch1_phase  ch2_phase  distance
79   0.011960 -0.003418  0.005127 -0.019530     -15.95    -75.290       0.0
78  -0.009766 -0.005371 -0.015870  0.010010    -151.20    147.800       1.0
343  0.002197  0.010990  0.003662 -0.013180      78.69    -74.480       2.0
80  -0.002686  0.010740  0.011960  0.013430     104.00     48.300       3.0
341 -0.007080  0.009033  0.016600 -0.000977     128.10     -3.366       4.0

If I try this:

df['ch1_log_mag']=20*np.log10(np.abs(complex(df.ch1_real,df.ch1_imag)))

I get error: "TypeError: cannot convert the series to <class 'float'>", because I think cmath.complex cannot work on an array.

So I then experimented using loc to pick out the first element of ch1_real, for example, to then work out how use it to accomplish what I'm trying to do, but couldn't figure out how to do it:

df.loc[0,df['ch1_real']]

This produces a KeyError.

Brute forcing it works,

df['ch1_log_mag'] = 20 * np.log10(np.sqrt(df.ch1_real**2+ df.ch1_imag**2))

but, I believe it is more legible to use np.abs to get the magnitude, plus I'm more interested in understanding how dataframes and indexing dataframes work and why what I initially attempted does not work.

btw, what is the difference between df.ch1_real and df['ch1_real'] ? When do I use one vs. the other?

Edit: more attempts at solution I tried using apply, since my understanding is that it "applies" the function passed to it to each row (by default):

df.apply(complex(df['ch1_real'], df['ch1_imag']))

but this generates the same TypeError, since I think the issue is that complex cannot work on Series. Perhaps if I cast the series to float?

After reading this post, I tried using pd.to_numeric to convert a series to type float:

 dfUnique.apply(complex(pd.to_numeric(dfUnique['ch1_real'],errors='coerce'), pd.to_numeric(dfUnique['ch1_imag'],errors='coerce')))

to no avail.


回答1:


You can do simple multiplication with 1j which denotes the complex number 0+1j, see imaginary literals:

df['ch1_log_mag'] = 20 * np.log10((df.ch1_real + 1j * df.ch1_imag).abs())

complex(df.ch1_real, df.ch1_imag) doesn't work as it needs a float argument, not a whole series. df.loc[0,df['ch1_real']] is not a valid expression, as the second argument must be a string, not a series (df.loc[79,'ch1_real'] would work for accessing an element).
If you want to use apply it should be 20 * np.log10(df.apply(lambda x: complex(x.ch1_real, x.ch1_imag), 1).abs()) but as apply is just a disguised loop over the rows of the dataframe it's not recommended performancewise.

There's no difference between df.ch1_real and df['ch1_real'], it's a matter of personal preference. If your column name contains spaces or dots or the like you must use the latter form however.



来源:https://stackoverflow.com/questions/65738704/combining-real-and-imag-columns-in-dataframe-into-complex-number-to-obtain-magni

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!