问题
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