The Fourier transform of real-valued data is Hermitian symmetric (I usually just say conjugate symmetric), i.e., $X(f) = X^{*}(-f)$ where $*$ is conjugation and $X(f)$ is the Fourier transform of the real-valued data, $x(t)$. Since the spectrum is $S(f) = |X(f)|^{2} = X(f)X^{*}(f)$, the spectrum is symmetric about $f = 0$.
Now, when you take use the FFT in R
, it is storing the positive frequencies in the 1 through (n/2)+1 indices (the 1st is $f = 0$ and the last, (n/2)+1, is the Nyquist frequency, $f_{N} = \frac{1}{2 \Delta t}$ where $\Delta t$ is the sampling rate or time between samples).
The "negative" frequencies are thus stored in the (n/2)+2 through n indices. As mentioned, the negative frequencies in the spectrum are mirrored in the positive frequencies (except 0 and Nyquist) and so normally we only plot the first (n/2) + 1 frequencies as no more information is gained. You would plot all the frequencies if your data were complex-valued however.
So, the frequencies you are estimating the spectrum at depend on the sampling rate.
I say "negative" because since the Spectrum / Fourier transform are periodic.
A couple of notes if you're interested. The spec.pgram
function in R
isn't actually calculating the periodogram, it's calculating the spectrum using a 10% (by default) cosine taper. There are much better tapers around, specifically the zero-th order Slepian sequence is "the best" (optimal in a broadband bias sense). The Slepian sequences are what are used in the multitaper package (more below).
It is reasonably standard practice to zero-pad your series before estimating the spectrum. This helps to take care of circular autocorrelation and takes advantage of FFT efficiency (series length with small primes as factors are optimal). You also obtain a finer frequency mesh at which the spectrum is estimated (however, no information is gained as these points are basically interpolated). A by-product of zero-padding is that the plots can often look nicer as well.
I normally just zero-pad out to a factor of two, but this will depend on application. Say M is my zero-padded length, then:
$$M = 2^{\lfloor\log_{2}(n)\rfloor + 2}$$
Also, if you would like to use an optimal spectral estimator (in the bias / variance sense), there is a package called multitaper that can be used (the periodogram is horrendously biased (in a broad-band sense)). I posted a bit about it here: Power density spectrum formula in R
Hopefully that at least addressed your questions, but if not, please let me know and I'd be happy to try to help out.