I have sampling data obtained from an accelerometer, with the acceleration on each axis ('x', 'y' and 'z').
That data is stored as a Pandas DataFrame, with a column for each axis.
With that, I obtain the FFT like so:
import pandas as pd
from scipy import fft
from typing import Optional
def fft_raw(df: pd.DataFrame) -> pd.DataFrame:
    """Calculates the raw Fast Fourier Transform of a DataFrame
    Parameters
    ----------
    df : pd.DataFrame
        DataFrame whose FFT should be calculated
    Returns
    -------
    pd.DataFrame
        Raw FFT
    """
    fft_raw = pd.DataFrame()
    for c in df:
        fft_raw = fft_raw.join(
            pd.DataFrame(fft.rfft(np.array(df[c])), columns=[c]), how="outer"
        )
    return fft_raw
def norm_fft(fft_raw: pd.DataFrame, length: Optional[int] = None) -> pd.DataFrame:
    """Normalizes a raw FFT
    Parameters
    ----------
    fft_raw : pd.DataFrame
        Raw FFT to be normalized
    length : int, optional
        How many sample points were used for calculating the raw FFT
        It uses the length of `fft_raw` by default
    Returns
    -------
    pd.DataFrame
        Normalized FFT
    """
    if length is None:
        length = len(fft_raw)
    return 2.0 * (fft_raw.abs() / length)
It'll end up looking something like this:

I then want to extract the peaks from such FFT.
In the example given above, the peaks for the 'z' axis are, approx.:
  2.90 Hz at 0.15 g
 54.56 Hz at 0.90 g
106.22 Hz at 0.10 g
One thing I considered doing was filtering out all frequencies whose magnitude is below a given threshold (for the example, it could be around 0.1 g), and that'd give me a waveform with just the peaks in them.
The problem with that is that I'll still have a lot of sampling points around the peaks, as it usually "rises" up to the maximum for the peak, then "declines" back to near-nothing, and that takes up multiple points, not just one.
I then thought about trying to "split" the waveform into groups of points that represent a single peak, so I could then find their max, but I'm not quite sure of an efficient way of doing that.
I was trying to find a similar question, and then came across this one, but I couldn't get it to work, even after simplifying my data back to a Numpy Array.
So I decided to ask here if someone knows of an efficient way, preferably using Pandas, to get the peaks of the FFT.
