Ini eksperimen saya:
Saya menggunakan findPeaks
fungsi dalam paket kuantmod :
Saya ingin mendeteksi puncak "lokal" dalam toleransi 5, yaitu lokasi pertama setelah rangkaian waktu turun dari puncak lokal sebanyak 5:
aa=100:1
bb=sin(aa/3)
cc=aa*bb
plot(cc, type="l")
p=findPeaks(cc, 5)
points(p, cc[p])
p
Outputnya adalah
[1] 3 22 41
Tampaknya salah, karena saya mengharapkan lebih banyak "puncak lokal" dari 3 ...
Adakah pikiran?
r
time-series
Luna
sumber
sumber
findPeaks
muncul di balasan saya, @Adam. BTW, paketnya adalah "quantmod" .Jawaban:
Sumber kode ini diperoleh dengan mengetik namanya di prompt R. Outputnya adalah
Tes ini
x[pks - 1] - x[pks] > thresh
membandingkan setiap nilai puncak dengan nilai yang langsung berhasil dalam seri (bukan ke palung berikutnya dalam seri). Ini menggunakan perkiraan (kasar) dari ukuran kemiringan fungsi segera setelah puncak dan memilih hanya puncak-puncak di mana kemiringan melebihithresh
ukuran. Dalam kasus Anda, hanya tiga puncak pertama yang cukup tajam untuk lulus tes. Anda akan mendeteksi semua puncak dengan menggunakan default:sumber
Saya setuju dengan respons whuber tetapi hanya ingin menambahkan bahwa bagian "+2" dari kode, yang berupaya menggeser indeks agar sesuai dengan puncak yang baru ditemukan sebenarnya 'melampaui batas' dan seharusnya "+1". misalnya dalam contoh yang kita dapatkan:
ketika kami menyorot puncak-puncak yang ditemukan ini pada grafik (tebal merah):
kita melihat bahwa mereka secara konsisten 1 poin dari puncak yang sebenarnya.
akibatnya
seharusnya
pks[x[pks] - x[pks + 1] > thresh]
ataupks[x[pks] - x[pks - 1] > thresh]
PEMBARUAN BESAR
mengikuti pencarian saya sendiri untuk menemukan fungsi pencarian puncak yang memadai saya menulis ini:
'puncak' didefinisikan sebagai maksimum lokal dengan
m
poin di kedua sisi lebih kecil dari itu. karenanya, semakin besar parameterm
, semakin ketat prosedur pendanaan puncak. begitu:fungsi ini juga dapat digunakan untuk menemukan minimum lokal dari setiap vektor berurutan
x
viafind_peaks(-x)
.Catatan: saya sekarang telah meletakkan fungsi pada gitHub jika ada yang membutuhkannya: https://github.com/stas-g/findPeaks
sumber
Eek: Pembaruan kecil. Saya harus mengubah dua baris kode, batas-batas, (tambahkan -1 dan +1) untuk mencapai kesetaraan dengan fungsi Stas_G (menemukan beberapa 'puncak ekstra' terlalu banyak dalam kumpulan data nyata). Permintaan maaf untuk siapa pun yang tersesat sangat kecil oleh posting asli saya.
Saya telah menggunakan algoritma menemukan puncak Stas_g untuk beberapa waktu sekarang. Itu bermanfaat bagi saya untuk salah satu proyek saya selanjutnya karena kesederhanaannya. Namun saya perlu menggunakannya jutaan kali untuk perhitungan, jadi saya menulis ulang di Rcpp (Lihat paket Rcpp). Ini kira-kira 6x lebih cepat dari versi R dalam tes sederhana. Jika ada yang tertarik, saya telah menambahkan kode di bawah ini. Semoga saya membantu seseorang, Ceria!
Beberapa peringatan kecil. Fungsi ini mengembalikan indeks puncak dalam urutan terbalik dari kode R. Ini membutuhkan inhouse C ++ Sign function, yang saya sertakan. Itu belum sepenuhnya dioptimalkan tetapi keuntungan kinerja lebih lanjut tidak diharapkan.
sumber
for(q = lb; q < rb; ++q){ if(vY(q) > vY(i+1)){ isGreatest = false; } }
sebagai run terakhir melalui loop "menang", melakukan setara dengan:isGreatest = vY(rb-1) <= vY(rb)
. Untuk mencapai apa yang diklaim oleh komentar di atas garis tersebut, loop untuk perlu diubah menjadi:for(q = lb; isGreatest && (q < rb); ++q){ isGreatest = (vY(q) <= vY(i+1)) }
Pertama: Algoritme juga secara salah memanggil setetes ke kanan dataran datar karena
sign(diff(x, na.pad = FALSE))
akan menjadi 0 lalu -1 sehingga diffnya juga akan -1. Perbaikan sederhana adalah untuk memastikan bahwa sign-diff sebelum entri negatif bukanlah nol tetapi positif:Kedua: Algoritme memberikan hasil yang sangat lokal, misalnya 'naik' diikuti oleh 'turun' dalam menjalankan tiga istilah berturut-turut dalam urutan. Jika seseorang lebih tertarik pada maxima lokal dari fungsi berkesinambungan yang berisik, maka - mungkin ada hal-hal lain yang lebih baik di luar sana, tetapi ini adalah solusi saya yang murah dan langsung
memuluskan data yang sedikit. Juga gunakan kontrol yang disebutkan di atas terhadap flat kemudian drop-off.
saring kandidat ini dengan membandingkan, untuk versi loess-smoothed, rata-rata di dalam jendela berpusat di setiap puncak dengan rata-rata istilah lokal di luar.
sumber
Memang benar fungsinya juga mengidentifikasi akhir dari plateaux, tapi saya pikir ada perbaikan lain yang lebih mudah: Karena perbedaan pertama dari puncak nyata akan menghasilkan '1' lalu '-1', perbedaan kedua adalah '-2', dan kita bisa cek langsung
sumber
menggunakan Numpy
atau
menggunakan Panda
sumber