Saya ingin menghitung rata-rata satu set data sirkuler. Sebagai contoh, saya mungkin memiliki beberapa sampel dari pembacaan kompas. Masalahnya tentu saja adalah bagaimana menangani sampulnya. Algoritma yang sama mungkin berguna untuk tampilan jam.
Pertanyaan yang sebenarnya lebih rumit - apa arti statistik pada suatu bola atau dalam ruang aljabar yang "membungkus", misalnya grup aditif mod n. Jawabannya mungkin tidak unik, misalnya rata-rata 359 derajat dan 1 derajat bisa 0 derajat atau 180, tetapi secara statistik 0 terlihat lebih baik.
Ini adalah masalah pemrograman yang nyata bagi saya dan saya berusaha membuatnya tidak terlihat seperti masalah matematika saja.
Jawaban:
Hitung satuan vektor dari sudut dan ambil sudut rata-rata.
sumber
Pertanyaan ini diperiksa secara rinci dalam buku: "Statistics On Spheres", Geoffrey S. Watson, Catatan Kuliah Universitas Arkansas dalam Ilmu Matematika, 1983 John Wiley & Sons, Inc. sebagaimana disebutkan di http: //catless.ncl. ac.uk/Risks/7.44.html#subj4 oleh Bruce Karsh.
Cara yang baik untuk memperkirakan sudut rata-rata, A, dari serangkaian pengukuran sudut a [i] 0 <= i
Metode yang diberikan oleh starblue adalah setara secara komputasi, tetapi alasannya lebih jelas dan mungkin lebih efisien secara program, dan juga bekerja dengan baik dalam kasus nol, jadi pujian baginya.
Subjek sekarang dieksplorasi lebih rinci di Wikipedia , dan dengan kegunaan lain, seperti bagian fraksional.
sumber
Saya melihat masalah - misalnya, jika Anda memiliki sudut 45 'dan sudut 315', rata-rata "alami" akan menjadi 180 ', tetapi nilai yang Anda inginkan sebenarnya 0'.
Saya pikir Starblue ke sesuatu. Hitung saja koordinat kartesian (x, y) untuk setiap sudut, dan tambahkan vektor-vektor yang dihasilkan bersamaan. Offset sudut dari vektor akhir harus menjadi hasil yang Anda inginkan.
Saya mengabaikan sekarang bahwa arah kompas dimulai di utara, dan bergerak searah jarum jam, sedangkan koordinat kartesian "normal" dimulai dengan nol di sepanjang sumbu X, dan kemudian pergi berlawanan arah jarum jam. Bagaimanapun, matematika harus bekerja dengan cara yang sama.
sumber
cos()
,sin()
danatan2()
memberikan perkiraan (yang baik, tapi masih off oleh 1 atau 2 ULP) sehingga semakin banyak Anda rata-rata, semakin kesalahan Anda termasuk.UNTUK KASUS KHUSUS DUA GILA:
Jawaban ((a + b) mod 360) / 2 adalah SALAH . Untuk sudut 350 dan 2, titik terdekat adalah 356, bukan 176.
Vektor unit dan solusi trigonometri mungkin terlalu mahal.
Yang saya dapat dari sedikit bermain-main adalah:
sumber
ackb benar bahwa solusi berbasis vektor ini tidak dapat dianggap sebagai rata-rata sudut yang sebenarnya, mereka hanya rata-rata dari rekan unit vektor. Namun, solusi yang disarankan ackb tampaknya tidak terdengar secara matematis.
Berikut ini adalah solusi yang secara matematis berasal dari tujuan meminimalkan (sudut [i] - avgAngle) ^ 2 (di mana perbedaan dikoreksi jika perlu), yang menjadikannya rata-rata aritmatika sebenarnya dari sudut.
Pertama, kita perlu melihat secara tepat kasus mana perbedaan antara sudut berbeda dengan perbedaan antara rekan-rekan nomor normalnya. Pertimbangkan sudut x dan y, jika y> = x - 180 dan y <= x + 180, maka kita dapat menggunakan perbedaan (xy) secara langsung. Kalau tidak, jika kondisi pertama tidak terpenuhi maka kita harus menggunakan (y + 360) dalam perhitungan alih-alih y. Sejalan dengan itu, jika kondisi kedua tidak terpenuhi maka kita harus menggunakan (y-360) daripada y. Karena persamaan kurva kita meminimalkan hanya perubahan pada titik-titik di mana ketidaksetaraan ini berubah dari true ke false atau sebaliknya, kita dapat memisahkan rentang penuh [0,360) menjadi satu set segmen, dipisahkan oleh titik-titik ini. Kemudian, kita hanya perlu menemukan minimum dari masing-masing segmen ini, dan kemudian minimum dari minimum setiap segmen, yang merupakan rata-rata.
Berikut adalah gambar yang menunjukkan di mana masalah terjadi dalam menghitung perbedaan sudut. Jika x terletak di area abu-abu maka akan ada masalah.
Untuk meminimalkan suatu variabel, tergantung pada kurva, kita dapat mengambil turunan dari apa yang ingin kita perkecil dan kemudian kita menemukan titik balik (yang merupakan tempat turunan = 0).
Di sini kita akan menerapkan gagasan meminimalkan perbedaan kuadrat untuk memperoleh rumus rata-rata aritmatika yang umum: jumlah (a [i]) / n. Kurva y = jumlah ((a [i] -x) ^ 2) dapat diminimalkan dengan cara ini:
Sekarang menerapkannya ke kurva dengan perbedaan kami yang disesuaikan:
b = himpunan bagian di mana perbedaan yang benar (sudut) a [i] -xc = himpunan bagian di mana perbedaan (sudut) yang benar (a [i] -360) -x cn = ukuran cd = bagian dari di mana perbaiki (sudut) yang benar (a [i] +360) -x dn = ukuran d
Ini saja tidak cukup untuk mendapatkan minimum, sementara itu bekerja untuk nilai normal, yang memiliki set tidak terikat, sehingga hasilnya pasti akan berada dalam kisaran set dan oleh karena itu valid. Kami membutuhkan minimum dalam rentang (ditentukan oleh segmen). Jika minimum kurang dari batas bawah segmen kami maka minimum segmen itu harus di batas bawah (karena kurva kuadrat hanya memiliki 1 titik balik) dan jika minimum lebih besar dari batas atas segmen kami maka minimum segmen adalah pada batas atas. Setelah kami memiliki minimum untuk setiap segmen, kami hanya menemukan yang memiliki nilai terendah untuk apa yang kami meminimalkan (jumlah ((b [i] -x) ^ 2) + jumlah (((c [i] -360 ) -b) ^ 2) + jumlah (((d [i] +360) -c) ^ 2)).
Berikut ini adalah gambar untuk kurva, yang menunjukkan bagaimana itu berubah pada titik di mana x = (a [i] +180)% 360. Kumpulan data yang dimaksud adalah {65,92.230.320.250}.
Berikut ini adalah implementasi dari algoritma di Jawa, termasuk beberapa optimisasi, kompleksitasnya adalah O (nlogn). Ini dapat dikurangi menjadi O (n) jika Anda mengganti jenis berbasis perbandingan dengan jenis berbasis non perbandingan, seperti jenis radix.
Mean aritmatika dari serangkaian sudut mungkin tidak setuju dengan ide intuitif Anda tentang apa yang seharusnya rata-rata. Sebagai contoh, rata-rata aritmatika dari himpunan {179.179.0.181.181} adalah 216 (dan 144). Jawaban yang segera Anda pikirkan mungkin 180, namun diketahui bahwa rata-rata aritmatika sangat dipengaruhi oleh nilai tepi. Anda juga harus ingat bahwa sudut bukan vektor, semenarik yang tampak ketika berhadapan dengan sudut terkadang.
Algoritma ini tentu saja juga berlaku untuk semua kuantitas yang mematuhi aritmatika modular (dengan penyesuaian minimal), seperti waktu dalam sehari.
Saya juga ingin menekankan bahwa meskipun ini adalah rata-rata sudut sebenarnya, tidak seperti solusi vektor, itu tidak berarti bahwa itu adalah solusi yang harus Anda gunakan, rata-rata vektor satuan yang sesuai mungkin adalah nilai yang Anda sebenarnya harus menggunakan.
sumber
Anda harus mendefinisikan rata-rata lebih akurat. Untuk kasus khusus dari dua sudut, saya dapat memikirkan dua skenario yang berbeda:
Saya tidak melihat bagaimana alternatif kedua dapat digeneralisasi untuk kasus lebih dari dua sudut.
sumber
Seperti semua rata-rata, jawabannya tergantung pada pilihan metrik. Untuk metrik M yang diberikan, rata-rata beberapa sudut a_k dalam [-pi, pi] untuk k dalam [1, N] adalah sudut a_M yang meminimalkan jumlah jarak kuadrat d ^ 2_M (a_M, a_k). Untuk nilai rata-rata tertimbang, cukup masukkan jumlah bobot w_k (sedemikian rupa sehingga sum_k w_k = 1). Itu adalah,
a_M = arg min_x jumlah_k w_k d ^ 2_M (x, a_k)
Dua pilihan metrik yang umum adalah metrik Frobenius dan Riemann. Untuk metrik Frobenius, ada rumus langsung yang sesuai dengan gagasan bantalan rata-rata dalam statistik sirkuler. Lihat "Cara dan Rata-rata dalam Grup Rotasi", Maher Moakher, Jurnal SIAM tentang Analisis dan Aplikasi Matriks, Volume 24, Edisi 1, 2002, untuk perinciannya.
http://link.aip.org/link/?SJMAEL/24/1/1
Berikut adalah fungsi untuk GNU Octave 3.2.4 yang melakukan perhitungan:
sumber
Saya ingin berbagi metode yang saya gunakan dengan mikrokontroler yang tidak memiliki kemampuan floating point atau trigonometri. Saya masih perlu "rata-rata" 10 pembacaan bantalan mentah untuk memuluskan variasi.
Itu tidak ideal; itu bisa pecah. Saya lolos dengan ini dalam kasus ini karena perangkat hanya berputar sangat lambat. Saya akan meletakkannya di sana kalau-kalau ada orang lain menemukan diri mereka bekerja di bawah pembatasan yang sama.
sumber
Dalam Bahasa Inggris:
Dengan python:
Larik sudut NX1 #numpy
sumber
Inilah solusi lengkapnya: (input adalah larik bantalan dalam derajat (0-360)
sumber
Dengan python, dengan sudut antara [-180, 180)
Detail:
Untuk rata-rata dua sudut ada dua rata-rata terpisah 180 °, tetapi kita mungkin menginginkan rata-rata yang lebih dekat.
Secara visual, rata-rata biru ( b ) dan hijau ( a ) menghasilkan titik teal:
Sudut 'membungkus' (mis. 355 + 10 = 5), tetapi aritmatika standar akan mengabaikan titik cabang ini. Namun jika sudut b berlawanan dengan titik cabang, maka ( b + g ) / 2 memberikan rata-rata terdekat: titik teal.
Untuk dua sudut manapun, kita dapat memutar masalah sehingga salah satu sudut berlawanan dengan titik cabang, melakukan rata-rata standar, lalu memutar kembali.
sumber
Saya akan menggunakan cara vektor menggunakan bilangan kompleks. Contoh saya adalah dalam Python, yang memiliki bilangan kompleks bawaan:
Perhatikan bahwa Python tidak perlu membuat daftar vektor sementara yang baru, semua hal di atas dapat dilakukan dalam satu langkah; Saya baru saja memilih cara ini untuk memperkirakan kode semu yang berlaku untuk bahasa lain juga.
sumber
Inilah solusi C ++ lengkap:
Dibutuhkan sudut dalam bentuk vektor ganda, dan mengembalikan rata-rata hanya sebagai ganda. Sudut harus dalam derajat, dan tentu saja rata-rata dalam derajat juga.
sumber
avgCos
adalah rata-rata komponen x, danavgSin
merupakan rata-rata komponen y. Parameter untuk fungsi arctangent adalahatan2( y, x )
. Jadi, bukankah seharusnya kode Anda menjadi:atan2( avgSin, avgCos )
??Berdasarkan jawaban Alnitak , saya telah menulis metode Java untuk menghitung rata-rata dari beberapa sudut:
Jika sudut Anda berada di radian:
Jika sudut Anda dalam derajat:
sumber
Inilah sebuah ide: bangun rata-rata secara iteratif dengan selalu menghitung rata-rata sudut yang paling dekat satu sama lain, dengan menjaga bobot.
Gagasan lain: temukan celah terbesar di antara sudut yang diberikan. Temukan titik yang membagi dua, dan kemudian pilih titik yang berlawanan pada lingkaran sebagai nol referensi untuk menghitung rata-rata.
sumber
Mari kita mewakili sudut-sudut ini dengan titik-titik pada keliling lingkaran.
Bisakah kita mengasumsikan bahwa semua titik ini jatuh pada setengah lingkaran yang sama? (Kalau tidak, tidak ada cara yang jelas untuk mendefinisikan "sudut rata-rata". Pikirkan dua titik pada diameter, misalnya 0 deg dan 180 deg --- adalah rata-rata 90 deg atau 270 deg? Apa yang terjadi ketika kita memiliki 3 atau lebih menyebarkan poin secara merata?)
Dengan asumsi ini, kami memilih titik sembarang pada setengah lingkaran itu sebagai "asal", dan mengukur kumpulan sudut yang diberikan sehubungan dengan asal ini (sebut ini "sudut relatif"). Perhatikan bahwa sudut relatif memiliki nilai absolut yang ketat kurang dari 180 derajat. Akhirnya, ambil rata-rata sudut relatif ini untuk mendapatkan sudut rata-rata yang diinginkan (relatif terhadap asal usul kita tentu saja).
sumber
Tidak ada "jawaban yang benar". Saya merekomendasikan membaca buku, KV Mardia dan PE Jupp, "Directional Statistics", (Wiley, 1999), untuk analisis menyeluruh.
sumber
(Hanya ingin berbagi sudut pandang saya dari Teori Estimasi atau Inferensi Statistik)
Uji coba Nimble adalah untuk mendapatkan estimasi MMSE ^ dari serangkaian sudut, tetapi ini adalah salah satu pilihan untuk menemukan arah "rata-rata"; seseorang juga dapat menemukan perkiraan MMAE ^, atau perkiraan lain sebagai arah "rata-rata", dan itu tergantung pada kesalahan arah pengukuran metrik Anda; atau lebih umum dalam teori estimasi, definisi fungsi biaya.
^ MMSE / MMAE sesuai dengan rata-rata kuadrat minimum / kesalahan absolut.
ackb berkata "Sudut rata-rata phi_avg harus memiliki properti yang sum_i | phi_avg-phi_i | ^ 2 menjadi minimal ... mereka rata-rata sesuatu, tetapi bukan sudut"
---- Anda mengukur kesalahan dalam arti kuadrat dan itu salah satu cara yang paling umum, namun, bukan satu-satunya cara. Jawaban yang disukai oleh kebanyakan orang di sini (yaitu, penjumlahan vektor satuan dan mendapatkan sudut hasilnya) sebenarnya adalah salah satu solusi yang masuk akal. Ini (dapat dibuktikan) penduga ML yang berfungsi sebagai arah "rata-rata" yang kita inginkan, jika arah vektor dimodelkan sebagai distribusi von Mises. Distribusi ini tidak mewah, dan hanya distribusi sampel secara berkala dari Guassian 2D. Lihat Persamaan. (2.179) dalam buku Bishop "Pengenalan Pola dan Pembelajaran Mesin". Sekali lagi, tidak berarti itu satu-satunya yang terbaik untuk mewakili arah "rata-rata", namun, itu cukup masuk akal yang memiliki justifikasi teoretis yang baik dan implementasi sederhana.
Nimble berkata "ackb benar bahwa solusi berbasis vektor ini tidak dapat dianggap sebagai rata-rata sudut sejati, mereka hanya rata-rata rekan-rekan vektor satuan"
----ini tidak benar. "Unit vector counterpart" mengungkapkan informasi arah vektor. Sudut adalah kuantitas tanpa mempertimbangkan panjang vektor, dan vektor satuan adalah sesuatu dengan informasi tambahan bahwa panjangnya adalah 1. Anda dapat menentukan vektor "satuan" Anda dengan panjang 2, tidak masalah.
sumber
Berikut ini adalah solusi aritmatika sepenuhnya menggunakan moving average dan berhati-hati untuk menormalkan nilai-nilai. Cepat dan memberikan jawaban yang benar jika semua sudut berada di satu sisi lingkaran (dalam 180 ° satu sama lain).
Secara matematis sama dengan menambahkan offset yang menggeser nilai ke dalam kisaran (0, 180), menghitung rata-rata dan kemudian mengurangi offset.
Komentar menggambarkan kisaran nilai apa yang dapat diambil pada waktu tertentu
sumber
Yah saya sangat terlambat ke pesta, tetapi saya pikir saya akan menambah nilai 2 sen saya karena saya tidak bisa menemukan jawaban yang pasti. Pada akhirnya saya mengimplementasikan versi Java berikut dari metode Mitsuta yang, saya harap, memberikan solusi yang sederhana dan kuat. Terutama karena Deviasi Standar memberikan dispersi ukuran dan, jika sd == 90, menunjukkan bahwa sudut input menghasilkan rata-rata yang ambigu.
EDIT: Sebenarnya saya menyadari bahwa implementasi asli saya dapat lebih disederhanakan, sebenarnya sangat sederhana mengingat semua percakapan dan trigonometri terjadi pada jawaban lainnya.
... dan untuk Anda semua (Java) Geeks di luar sana, Anda dapat menggunakan pendekatan di atas untuk mendapatkan sudut rata-rata dalam satu baris.
sumber
Alnitak memiliki solusi yang tepat. Solusi Nick Fortescue secara fungsional sama.
Untuk kasus khusus di mana
(jumlah (x_komponen) = 0,0 && jumlah (y_komponen) = 0,0) // mis. 2 sudut 10 dan 190. derajat ea.
gunakan 0,0 derajat sebagai jumlah
Secara komputasional Anda harus menguji untuk kasus ini karena atan2 (0., 0.) tidak ditentukan dan akan menghasilkan kesalahan.
sumber
Sudut rata-rata phi_avg harus memiliki properti yang sum_i | phi_avg-phi_i | ^ 2 menjadi minimal, di mana perbedaannya harus dalam [-Pi, Pi) (karena mungkin lebih pendek untuk pergi sebaliknya!). Ini mudah dicapai dengan menormalkan semua nilai input ke [0, 2Pi), menjaga phi_run rata-rata berjalan, dan memilih normalisasi | phi_i-phi_run | ke [-Pi, Pi) (dengan menambahkan atau mengurangi 2Pi). Kebanyakan saran di atas melakukan sesuatu yang lain yang tidak memiliki properti minimal, yaitu, mereka rata-rata sesuatu , tetapi tidak sudut.
sumber
Saya memecahkan masalah dengan bantuan jawaban dari @David_Hanak. Seperti yang ia nyatakan:
Jadi yang saya lakukan adalah menghitung rata-rata semua sudut. Dan kemudian semua sudut yang kurang dari ini, tingkatkan sebesar 360. Kemudian hitung ulang rata-rata dengan menambahkan semuanya dan membaginya dengan panjangnya.
Bekerja dengan sempurna.
sumber
Fungsi python:
sumber
Anda dapat menggunakan fungsi ini di Matlab:
sumber
Anda dapat melihat solusi dan sedikit penjelasan di tautan berikut, untuk bahasa pemrograman APAPUN: https://rosettacode.org/wiki/Averages/Mean_angle
Misalnya, solusi C ++ :
Keluaran:
Atau solusi Matlab :
sumber
Sementara jawaban starblue memberikan sudut vektor satuan rata-rata, dimungkinkan untuk memperluas konsep rata-rata aritmatika ke sudut jika Anda menerima bahwa mungkin ada lebih dari satu jawaban dalam kisaran 0 hingga 2 * pi (atau 0 ° hingga 360 °). Misalnya, rata-rata 0 ° dan 180 ° dapat 90 ° atau 270 °.
Rata-rata aritmatika memiliki properti sebagai nilai tunggal dengan jumlah minimum jarak kuadrat ke nilai input. Jarak sepanjang lingkaran satuan antara dua vektor satuan dapat dengan mudah dihitung sebagai cosinus terbalik dari produk titik mereka. Jika kita memilih vektor satuan dengan meminimalkan jumlah cosinus terbalik kuadrat dari produk titik vektor kita dan setiap vektor satuan input, maka kita memiliki rata-rata yang setara. Sekali lagi, perlu diingat bahwa mungkin ada dua atau lebih minimum dalam kasus luar biasa.
Konsep ini dapat diperluas ke sejumlah dimensi, karena jarak di sepanjang unit sphere dapat dihitung dengan cara yang sama persis dengan jarak di sepanjang lingkaran unit - cosinus terbalik dari produk titik dari dua vektor satuan.
Untuk lingkaran kita dapat memecahkan rata-rata ini dalam beberapa cara, tetapi saya mengusulkan algoritma O (n ^ 2) berikut (sudut dalam radian, dan saya menghindari menghitung vektor satuan):
Jika semua sudut berada dalam 180 ° satu sama lain, maka kita bisa menggunakan algoritma O (n) + O (sort) yang lebih sederhana (lagi-lagi menggunakan radian dan menghindari penggunaan vektor satuan):
Untuk menggunakan derajat, cukup ganti pi dengan 180. Jika Anda berencana untuk menggunakan lebih banyak dimensi maka Anda kemungkinan besar harus menggunakan metode berulang untuk menyelesaikan rata-rata.
sumber
Masalahnya sangat sederhana. 1. Pastikan semua sudut berada di antara -180 dan 180 derajat. 2. a Tambahkan semua sudut non-negatif, ambil rata-rata, dan COUNT berapa banyak 2. b. Tambahkan semua sudut negatif, ambil rata-rata dan COUNT berapa banyak. 3. Ambil perbedaan pos_average minus neg_average Jika perbedaan lebih dari 180 maka ubah perbedaan menjadi 360 perbedaan minus. Kalau tidak, ubah saja tanda perbedaannya. Perhatikan bahwa perbedaan selalu non-negatif. Average_Angle sama dengan pos_average plus selisih kali "berat", jumlah negatif dibagi dengan jumlah negatif dan positif
sumber
Berikut adalah beberapa kode java untuk sudut rata-rata, saya pikir cukup kuat.
sumber
Saya memiliki metode yang berbeda dari @Starblue yang memberikan jawaban yang "benar" untuk beberapa sudut yang diberikan di atas. Sebagai contoh:
Ini menggunakan jumlah atas perbedaan antara sudut berurutan. Kode (dalam Matlab):
sumber
[-90,90,40]
dan[90,-90,40]
; Saya tidak berpikir rata-rata non-komutatif adalah yang sangat berguna.