Tampaknya tidak ada fungsi yang hanya menghitung rata-rata bergerak pada numpy / scipy, yang mengarah ke solusi berbelit - belit .
Pertanyaan saya ada dua:
- Apa cara termudah untuk (benar) menerapkan rata-rata bergerak dengan numpy?
- Karena hal ini tampaknya tidak sepele dan rawan kesalahan, adakah alasan yang baik untuk tidak menyertakan baterai dalam casing ini?
python
numpy
scipy
time-series
moving-average
goncalopp.dll
sumber
sumber
Jawaban:
Jika Anda hanya ingin langsung non-tertimbang rata-rata bergerak, Anda dapat dengan mudah menerapkannya dengan
np.cumsum
, yangmungkinmerupakan metode cepat dari FFT berdasarkan:EDIT Memperbaiki kesalahan pengindeksan off-by-one yang ditemukan oleh Bean dalam kode. EDIT
Jadi saya kira jawabannya adalah: sangat mudah untuk diterapkan, dan mungkin numpy sudah sedikit membengkak dengan fungsi khusus.
sumber
ret[n:] -= ret[:-n]
TIDAK SAMA denganret[n:] = ret[n:] - ret[:-n]
. Saya telah memperbaiki kode dalam jawaban ini. Edit: Tidak ada orang lain yang mengalahkan saya untuk itu.Kurangnya NumPy pada fungsi spesifik domain tertentu mungkin karena disiplin Tim Inti dan ketaatan pada arahan utama NumPy: menyediakan tipe array dimensi-N , serta fungsi untuk membuat, dan mengindeks array tersebut. Seperti banyak tujuan dasar, yang satu ini tidak kecil, dan NumPy melakukannya dengan cemerlang.
SciPy (yang jauh) lebih besar berisi koleksi perpustakaan khusus domain yang jauh lebih besar (disebut subpaket oleh SciPy devs) - misalnya, pengoptimalan numerik ( optimalkan ), pemrosesan sinyal ( sinyal ), dan kalkulus integral ( integrasi ).
Dugaan saya adalah bahwa fungsi yang Anda cari setidaknya ada di salah satu subpaket SciPy ( mungkin scipy.signal ); Namun, saya akan melihat pertama di koleksi scikits SciPy , mengidentifikasi scikit yang relevan dan mencari fungsi yang menarik di sana.
Scikits adalah paket yang dikembangkan secara independen berdasarkan NumPy / SciPy dan diarahkan ke disiplin teknis tertentu (misalnya, scikits-image , scikits-learn , dll.) Beberapa di antaranya (khususnya, OpenOpt yang mengagumkan untuk pengoptimalan numerik) sangat dihargai, proyek matang jauh sebelum memilih untuk berada di bawah rubrik scikits yang relatif baru . The Scikits homepage suka daftar di atas sekitar 30 seperti scikits , meskipun setidaknya beberapa dari mereka tidak lagi di bawah pengembangan aktif.
Mengikuti saran ini akan membawa Anda ke seri waktu scikits ; namun, paket tersebut tidak lagi aktif dalam pengembangan; Akibatnya, Panda telah menjadi, AFAIK, perpustakaan deret waktu berbasis NumPy de facto .
Panda memiliki beberapa fungsi yang dapat digunakan untuk menghitung rata-rata bergerak ; yang paling sederhana mungkin adalah rolling_mean , yang Anda gunakan seperti ini:
Sekarang, panggil saja fungsi rolling_mean yang lewat di objek Seri dan ukuran jendela , yang dalam contoh saya di bawah ini adalah 10 hari .
verifikasi bahwa itu berfungsi - misalnya, membandingkan nilai 10 - 15 dalam seri asli versus Seri baru yang dihaluskan dengan rata-rata bergulir
Fungsi rolling_mean, bersama dengan sekitar selusin fungsi lainnya secara informal dikelompokkan dalam dokumentasi Pandas di bawah fungsi rubrik jendela bergerak ; kedua, grup fungsi terkait di Pandas disebut sebagai fungsi dengan bobot eksponensial (misalnya, ewma , yang menghitung rata-rata bergerak tertimbang bergerak secara eksponensial). Fakta bahwa grup kedua ini tidak termasuk dalam yang pertama ( fungsi jendela bergerak ) mungkin karena transformasi dengan pembobotan eksponensial tidak bergantung pada jendela dengan panjang tetap
sumber
Cara sederhana untuk mencapai ini adalah dengan menggunakan
np.convolve
. Ide di balik ini adalah untuk memanfaatkan cara konvolusi diskrit dihitung dan menggunakannya untuk mengembalikan rata-rata bergulir . Hal ini dapat dilakukan dengan cara berbelit-belit dengan urutannp.ones
yang panjangnya sama dengan panjang jendela geser yang kita inginkan.Untuk melakukannya, kita dapat menentukan fungsi berikut:
Fungsi ini akan mengambil konvolusi dari urutan
x
dan urutan panjangnyaw
. Perhatikan bahwa yang dipilihmode
adalahvalid
agar hasil kali konvolusi hanya diberikan untuk titik-titik di mana urutannya tumpang tindih sepenuhnya.Beberapa contoh:
Untuk rata-rata bergerak dengan panjang jendela,
2
kita akan memiliki:Dan untuk jendela panjang
4
:Bagaimana cara
convolve
kerjanya?Mari kita lihat lebih mendalam cara penghitungan konvolusi diskrit. Fungsi berikut bertujuan untuk mereplikasi cara
np.convolve
menghitung nilai keluaran:Yang mana, untuk contoh yang sama di atas juga akan menghasilkan:
Jadi apa yang dilakukan pada setiap langkah adalah mengambil produk dalam antara array satu dan jendela saat ini . Dalam hal ini perkalian dengan
np.ones(w)
berlebihan karena kita langsung mengambilsum
urutannya.Di bawah ini adalah contoh bagaimana keluaran pertama dihitung sehingga sedikit lebih jelas. Misalkan kita menginginkan jendela
w=4
:Dan keluaran berikut akan dihitung sebagai:
Dan seterusnya, mengembalikan rata-rata bergerak dari urutan setelah semua tumpang tindih dilakukan.
sumber
mode='valid'
kaleng diganti dengan'same'
. Hanya dalam kasus ini, titik tepi akan tertarik ke arah nol.Berikut ini berbagai cara untuk melakukan ini, bersama dengan beberapa tolok ukur. Metode terbaik adalah versi yang menggunakan kode yang dioptimalkan dari pustaka lain. The
bottleneck.move_mean
Metode mungkin terbaik di sekitar. Thescipy.convolve
Pendekatan ini juga sangat cepat, extensible, dan sintaksis dan konseptual sederhana, tetapi tidak baik skala untuk nilai-nilai jendela yang sangat besar. Thenumpy.cumsum
Metode baik jika Anda membutuhkan murninumpy
pendekatan.Catatan: Beberapa di antaranya (misalnya
bottleneck.move_mean
) tidak berada di tengah, dan akan menggeser data Anda.Pengaturan waktu, Jendela kecil (n = 3)
Pengaturan waktu, Jendela besar (n = 1001)
Memori, Jendela kecil (n = 3)
Memori, Jendela besar (n = 1001)
sumber
Jawaban yang menggunakan Pandas ini diadaptasi dari atas, karena
rolling_mean
sudah bukan bagian dari Panda lagiSekarang, panggil saja fungsi
rolling
pada dataframe dengan ukuran jendela, yang dalam contoh saya di bawah ini adalah 10 hari.sumber
Saya rasa ini bisa diselesaikan dengan mudah dengan menggunakan bottleneck
Lihat contoh dasar di bawah ini:
Ini memberikan rata-rata pergerakan di sepanjang setiap sumbu.
"mm" adalah arti bergerak untuk "a".
"jendela" adalah jumlah entri maksimal yang perlu dipertimbangkan untuk mean bergerak.
"min_count" adalah jumlah minimum entri yang perlu dipertimbangkan untuk memindahkan mean (misalnya untuk elemen pertama atau jika array memiliki nilai nan).
Bagian baiknya adalah Bottleneck membantu menangani nilai-nilai nan dan juga sangat efisien.
sumber
Jika Anda ingin menjaga kondisi tepi dengan hati-hati ( menghitung rata-rata hanya dari elemen yang tersedia di tepi ), fungsi berikut akan membantu.
sumber
Coba kode ini. Saya pikir ini lebih sederhana dan melakukan pekerjaan itu. lookback adalah jendela rata-rata bergerak.
Di bagian
Data[i-lookback:i, 0].sum()
Saya telah meletakkan0
untuk merujuk ke kolom pertama dari kumpulan data tetapi Anda dapat meletakkan kolom apa pun yang Anda suka jika Anda memiliki lebih dari satu kolom.sumber
Saya sebenarnya menginginkan perilaku yang sedikit berbeda dari jawaban yang diterima. Saya sedang membangun ekstraktor fitur rata-rata bergerak untuk
sklearn
pipa, jadi saya mensyaratkan bahwa keluaran rata-rata bergerak memiliki dimensi yang sama dengan masukan. Yang saya inginkan adalah rata-rata bergerak mengasumsikan rangkaian tetap konstan, yaitu rata-rata bergerak[1,2,3,4,5]
dengan jendela 2 akan memberikan[1.5,2.5,3.5,4.5,5.0]
.Untuk vektor kolom (kasus penggunaan saya) kita dapatkan
Dan untuk array
Tentu saja, seseorang tidak harus mengasumsikan nilai konstan untuk padding, tetapi melakukannya harus cukup dalam banyak kasus.
sumber
talib berisi alat rata-rata bergerak sederhana, serta alat rata-rata serupa lainnya (yaitu rata-rata bergerak eksponensial). Di bawah ini membandingkan metode dengan beberapa solusi lainnya.
Satu peringatan adalah bahwa yang nyata harus memiliki elemen
dtype = float
. Jika tidak, kesalahan berikut dimunculkansumber
Berikut ini adalah implementasi cepat menggunakan numba (perhatikan jenisnya). Perhatikan itu memang mengandung nans di mana digeser.
sumber
sumber
Saya menggunakan baik solusi jawaban yang diterima , sedikit dimodifikasi agar memiliki panjang yang sama untuk keluaran sebagai masukan, atau
pandas
'versi seperti yang disebutkan dalam komentar jawaban lain. Saya meringkas keduanya di sini dengan contoh yang dapat direproduksi untuk referensi di masa mendatang:sumber
Dengan membandingkan solusi di bawah ini dengan solusi yang menggunakan cumsum numpy, solusi ini memakan waktu hampir separuh . Ini karena tidak perlu melalui seluruh larik untuk melakukan cumsum dan kemudian melakukan semua pengurangan. Selain itu, cumsum bisa menjadi " berbahaya " jika arraynya besar dan jumlahnya besar ( kemungkinan meluap ). Tentu saja, di sini juga ada bahaya tetapi setidaknya dijumlahkan hanya angka-angka penting.
sumber