Fast Fourier Transform in R. What am I doing wrong?

I am a non-expert in Fourier analysis and quite don't get what R's function fft() does. Even after crossreading a lot I couldnt figure it out. I built an example. which looks like: I ASSUME that fft expects a vector recorded over a timespan of 1 second, so I divide by the timespan

I am a non-expert in Fourier analysis and quite don't get what R's function fft() does. Even after crossreading a lot I couldnt figure it out. I built an example.

require(ggplot2) freq <- 200 #sample frequency in Hz duration <- 3 # length of signal in seconds #arbitrary sine wave x <- seq(-4*pi,4*pi, length.out = freq*duration) y <- sin(0.25*x) + sin(0.5*x) + sin(x) 

which looks like:

enter image description here

fourier <- fft(y) #frequency "amounts" and associated frequencies amo <- Mod(fft(y)) freqvec <- 1:length(amo) 

I ASSUME that fft expects a vector recorded over a timespan of 1 second, so I divide by the timespan

freqvec <- freqvec/duration #and put this into a data.frame df <- data.frame(freq = freqvec, ammount = amo) 

Now I ASSUMABLY can/have to omit the second half of the data.frame since the frequency "amounts" are only significant to half of the sampling rate due to Nyquist.

df <- df[(1:as.integer(0.5*freq*duration)),] 

For plotting I discretize a bit

df.disc <- data.frame(freq = 1:100) cum.amo <- numeric(100) for (i in 1:100){ cum.amo[i] <- sum(df$ammount[c(3*i-2,3*i-1,3*i)]) } df.disc$ammount <- cum.amo 

The plot function for the first 20 frequencies:

df.disc$freq <- as.factor(df.disc$freq) ggplot(df.disc[1:20,], aes(x=freq, y=ammount)) + geom_bar(stat = "identity") 

The result:

enter image description here

Is this really a correct spectrogram of the above function? Are my two assumptions correct? Where is my mistake? If there is no, what does this plot now tell me?

EDIT: Here is a picture without discretization:

enter image description here

THANKS to all of you,

Micha.

4

1 Answer

Okay, okay. Due to the generally inferior nature of my mistake the solution is quite trivial. I wrote freq = 200 and duration = 3. But the real duration is from -4pi to 4 pi, hence 8pi resulting in a "real" sample frequency of 1/ ((8*pi)/600) = 23.87324 which does not equal 200. Replacing the respective lines in the example code by

freq <- 200 #sample frequency in Hz duration <- 6 # length of signal in seconds x <- seq(0,duration, length.out = freq*duration) y <- sin(4*pi*x) + sin(6*pi*x) + sin(8*pi*x) 

(with a more illustrative function) yields the correct frequencies as demonstrated by the following plot (restricted to the important part of the frequency domain):

enter image description here

ncG1vNJzZmirpJawrLvVnqmfpJ%2Bse6S7zGiorp2jqbawutJoaXBrZGh%2Bc4WOn5isrF2bvLa%2ByJ6pZqyilru0ss6rpGahnmK%2FbsPHmqtmmZ1itm6wzqKloGWnp7yvsw%3D%3D

 Share!