[英]Perform Fourier Analysis to a Time Series in R
我想使用 R 對時間序列執行傅立葉變換。我想:
這是數據的鏈接: 鏈接到數據
這是我的初始代碼。
dat <- read.csv("Baguio.csv",header=FALSE)
y <- dat$V1
ssp <-spectrum(y)
t <- 1:73
per <- 1/ssp$freq[ssp$spec==max(ssp$spec)]
reslm <- lm(y ~ sin(2*pi/per*t)+cos(2*pi/per*t))
rg <- diff(range(y))
#blue dashed line
plot(y~t,ylim=c(min(y)-0.1*rg,max(y)+0.1*rg))
lines(fitted(reslm)~t,col=4,lty=2)
#green line 2nd harmonics
reslm2 <- lm(y ~ sin(2*pi/per*t)+cos(2*pi/per*t)+sin(4*pi/per*t)+cos(4*pi/per*t))
lines(fitted(reslm2)~t,col=3)
有沒有辦法簡化這段代碼? 如果我必須達到 18 次諧波,則方程會變得非常長。 另外,我仍然不知道如何在這里添加諧波。
提前謝謝了,
一個更簡單的解決方案是使用快速傅里葉變換 ( fft
)
dat <- read.csv("Baguio.csv", header=FALSE)
y <- dat$V1
t <- 1:73
rg <- diff(range(y))
nff = function(x = NULL, n = NULL, up = 10L, plot = TRUE, add = FALSE, main = NULL, ...){
#The direct transformation
#The first frequency is DC, the rest are duplicated
dff = fft(x)
#The time
t = seq(from = 1, to = length(x))
#Upsampled time
nt = seq(from = 1, to = length(x)+1-1/up, by = 1/up)
#New spectrum
ndff = array(data = 0, dim = c(length(nt), 1L))
ndff[1] = dff[1] #Always, it's the DC component
if(n != 0){
ndff[2:(n+1)] = dff[2:(n+1)] #The positive frequencies always come first
#The negative ones are trickier
ndff[length(ndff):(length(ndff) - n + 1)] = dff[length(x):(length(x) - n + 1)]
}
#The inverses
indff = fft(ndff/73, inverse = TRUE)
idff = fft(dff/73, inverse = TRUE)
if(plot){
if(!add){
plot(x = t, y = x, pch = 16L, xlab = "Time", ylab = "Measurement",
main = ifelse(is.null(main), paste(n, "harmonics"), main))
lines(y = Mod(idff), x = t, col = adjustcolor(1L, alpha = 0.5))
}
lines(y = Mod(indff), x = nt, ...)
}
ret = data.frame(time = nt, y = Mod(indff))
return(ret)
}
然后我們需要調用res
,將時間序列作為x
,將諧波數作為n
並將上采樣(因此我們在原始點旁邊繪制時間點)作為up
。
png("res_18.png")
res = nff(x = y, n = 18L, up = 100L, col = 2L)
dev.off()
要獲得 5 次到 18 次諧波的總和,這只是系列之間的差異
sum5to18 = nff(x = y, n = 18L, up = 10L, plot = FALSE)
sum5to18$y = sum5to18$y - nff(x = y, n = 4L, up = 10L, plot = FALSE)$y
png("sum5to18.png")
plot(sum5to18, pch = 16L, xlab = "Time", ylab = "Measurement", main = "5th to 18th harmonics sum", type = "l", col = 2)
dev.off()
添加參數add
和col
允許我們繪制多個波以及特定顏色
colors = rainbow(36L, alpha = 0.3)
nff(x = y, n = 36L, up = 100L, col = colors[1])
png("all_waves.png")
for(i in 1:18){
ad = ifelse(i == 1, FALSE, TRUE)
nff(x = y, n = i, up = 100L, col = colors[i], add = ad, main = "All waves up to 18th harmonic")
}
dev.off()
有沒有辦法提取每個系列的數據然后保存為 csv 文件。 所以在這個例子中,我應該有 18 個 csv 文件用於 18 個波。
我編輯了代碼以允許 0 諧波(基本上是平均值),所以現在您將單獨的波提取為:
sep = array(data = NA_real_, dim = c(7300L, 2 + 18), dimnames = list(NULL, c("t", paste0("H", 0:18))))
sep[,1:2] = as.matrix(nff(x = y, n = 0, up = 100L, plot = FALSE))
for(i in 1:18L){
sep[,i+2] = nff(x = y, n = i, up = 100L, plot = FALSE)$y - nff(x = y, n = i-1, up = 100L, plot = FALSE)$y
}
然后你可以使用write.table
來寫一個 csv 文件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.