J'ai Noisy Data pour lequel je veux calculer fréquence et amplitude. Les échantillons ont été collectés toutes les 1 / 100e seconde. De ces tendances, je crois que la fréquence d'être ~ 0.3
P>
Lorsque j'utilise numpy code>
FFT code>, je finis à obtenir une très haute fréquence (36,32 / sec) qui n'est clairement pas correcte. J'ai essayé de filtrer les données avec
pandas code>
rolling_mean code> pour supprimer le bruit avant la FFT, mais cela n'a pas trop fonctionné. P>
import pandas as pd
from numpy import fft
import numpy as np
import matplotlib.pyplot as plt
Moisture_mean_x = pd.read_excel("signal.xlsx", header = None)
Moisture_mean_x = pd.rolling_mean(Moisture_mean_x, 10) # doesn't helps
Moisture_mean_x = Moisture_mean_x.dropna()
Moisture_mean_x = Moisture_mean_x -Moisture_mean_x.mean()
frate = 100. #/sec
Hn = fft.fft(Moisture_mean_x)
freqs = fft.fftfreq(len(Hn), 1/frate)
idx = np.argmax(np.abs(Hn))
freq_in_hertz = freqs[idx]
6 Réponses :
J'espère que cela peut vous aider. P>
https://scipy-cookbook.readthedocs.io/items/butterworthbandpass.html p>
Vous devez filtrer uniquement la bande autour de la fréquence attendue et améliorer le rapport de bruit du signal avant d'appliquer la FFT. P>
EDIT: P>
Mark Ransom a donné une réponse plus intelligente, si vous devez faire la FFT, vous pouvez simplement couper le bruit après la transformation. Cela ne donnera pas un résultat pire qu'un filtre. P>
Pourquoi devez-vous filtrer? Mark Ransom Commentaire à l'autre post similaire. Pourquoi une valeur de 10 conduirait-elle à une moyenne géométrique?
Désolé, c'était typo. J'avais essayé rolling_mean (.., 10) code> et a reçu 36,4 Hz.
ARGH, vous avez raison, la réponse de la marque est la plus intelligente. J'ai mal compris les données de la demande. En fait, je ne comprends pas pourquoi sa réponse a été votée. +1
Vous devez utiliser un filtre passe-bas, qui doit conserver les variations périodiques plus grandes et lisser d'abord certaines des trucs de fréquence la plus élevée. Après cela, alors peut faire FFT pour obtenir les sommets. Voici un Recette du filtre à sapin généralement utilisé pour ce type de chose exacte. p>
Le filtrage est totalement redondant, la FFT divise déjà des trucs par la fréquence. Il est juste nécessaire d'ignorer ces parties du résultat de la FFT qui correspondent aux fréquences en dehors de la gamme d'intérêts.
Un FFT est une banque de filtres. Il suffit de rechercher le pic de magnitude
Merci. J'ai également pensé à cela, mais je n'ai donné qu'un seul échantillon pour la question ici, alors que j'ai des centaines de tels signaux à analyser. La sélection de la gamme de fréquences attendue manuellement sera très fastidieuse. Y a-t-il un meilleur moyen de vous automatiquement calculer cette gamme de fréquences?
Vous ne pouvez pas filtrer sans savoir quelles fréquences pour essayer de supprimer (et donc ce qui reste). Même une moyenne mobile est un filtre (de mauvaise qualité). Vous devez donc savoir quelle gamme à espérer ou laisser le résultat bruyant non filtré et prendre ce que vous obtenez.
Je comprends que la moyenne mobile est un filtre de mauvaise qualité, mais je m'attendais à cela me rapprocherait de la fréquence attendue. Mais, même si j'utilisais Rolling Working Mean (..., 100) code> qui me donne un signal assez lissé [1], le résultat reste 34,8 Hz! Cela me donne sentir que je manque quelque chose. [1] Dropbox.com/s/75e0pgdcdzue9a5/smooth_signal.png?dl = 0
Il n'est pas nécessaire de filtrer le signal à l'avance, car la FFT est em> un filtre. Il suffit de sauter ces parties de la FFT correspondant aux fréquences que vous savez contenir beaucoup de bruit - zéro-les ou les exclure autrement. P>
Non, vous n'êtes pas obligé. Le signal est valorisé réel, alors étudier ainsi que le composant de fréquence négatif est redondant et conduira au même résultat.
@ GG349 Absolument correct, je n'ai pas réalisé que FFT renvoyait des valeurs complexes non réelles. Je vais supprimer les parties inexactes de cette réponse, qui devrait en être la plupart.
@MarkRansom Je suis d'accord, et cela semble être la seule solution jusqu'à présent. Mais, je me demande même si j'avais complètement le bruit le signal pour calculer le Fréquence, le résultat reste 34,8 Hz! Cela me donne un sentiment que je manque quelques étapes dans le code.
Vous avez raison, il y a quelque chose qui ne va pas. Il faut expliquer à Explictiy Demander aux Pandas pour la colonne Zeroth:
Hn = np.fft.fft(Moisture_mean_x[0])
En effet. Et maintenant, aucun filtrage n'est également nécessaire. Merci!
semble que @tillsten em> a déjà répondu à votre question, mais voici une certaine confirmation supplémentaire. La première intrigue est vos données (zéro moyenne et je l'ai changée à un CSV). La seconde est la densité spectrale de puissance et vous pouvez voir une masse grasse avec un pic à ~ 0,3 Hz. J'ai zoomé dans le troisième parcelle pour voir s'il y avait une deuxième fréquence cachée proche de la fréquence principale. Main freq: 0.32012805122
RMS amp: 0.0556044913489
Oui, j'ai également remarqué la fréquence cachée. Donc, je calcule la fréquence moyenne comme suit: freqs = fft.ftfreq (len (hn), 1 / frère); ind = np.arange (1, len (hn) / 2 + 1); psd = np.abs (hn [ind]) ** 2+ np.abs (hn [-ind]) ** 2; couper = 0,7 * psd.max (); ind1 = np.where (PSD> coupé); FREQ_IN_HERTZ = FREQS [IND [IND1]]. moyenne () code>.
Ça marche. Vous pouvez également trouver le deuxième pic par idx = np.argmax (np.abs (hn) [: 5]) code>
freq_in_hertz = freqs [idx] code> et il s'avère être 0.16006402561 (exactement la moitié de 0.32012 ...).
1) Le code va bien. 2) Pourquoi vous attendez-vous à 0,3 Hz? Je compte 6/8 pics en 2500 secondes, pour une estimation d'un Freq à faible freq dominant d'environ 0,0024 à 0,0032 Hz. 3) Quel est le problème avec 36.32 Hz, c'est-à-dire pourquoi êtes-vous sûr que cela n'est pas correct? 4) Si vous voulez vraiment préférer le signal avec une moyenne de rouleau, choisissez une taille de fenêtre différente de 1. Comme il est maintenant, l'appel à
rolling_mean () code> ne fait rien.
@ GG349 Je suppose que la photo affiche 2500 échantillons, pas de 2500 secondes. Cela rend votre plage de 0,24 à 0,32 Hz qui contient certainement 0,3.
@MarkRansom bien repéré
Désolé, c'était typo avec
rolling_mean code>, corrigé-le maintenant.