Çalışan medyanı hesaplamak için algoritmalar?


18

Daha küçük pencere boyutlarında n log nsıralama işe yarayabilir. Bunu başarmak için daha iyi algoritmalar var mı?


1
Bence bu, Stack Overflow'a taşınan ilk aday.

Muhtemelen, ama SO hakkında çok daha fazla açıklamaya ihtiyacı olacaktır.
walkytalky

2
Çoğu programcı "medyan" tanıyor. (sort (array)) [uzunluk / 2], unutanlar için yeterince büyük bir ipucudur. Ayrıca her yeni nokta için en temel noktasında, dizinin yarısında bir ikiye ayırma / ekleme yapmanız yeterlidir ...
Paul


2
Bir yorumdan daha fazla önemsiz olmakla birlikte, 3s medyanının kodu sadece a + b + c - max (a, b, c) - min (a, b. C) 'dir. Bağlar olsa bile bu işe yarar. Bir başkasının kodundan düşündüğümde bu sadece benim için açıktı (neden bu durumda (bu durumda) bir medyan almak ve çıkarmak ???) ve birkaç başka aynı reaksiyona sahip olabilir. max () ve min () genellikle süper hızlı işlevler olarak uygulanır. Ne yazık ki genel olarak böyle bir hile yok.
Nick Cox

Yanıtlar:


11

Bir medyan hesaplamak için bir dizi sıralamak kötü bir form. Ortamlar (ve diğer miktarlar) tipik olarak O ( n ) karmaşıklığı olan hızlı seçim algoritması kullanılarak hesaplanır .O(n)

Burada yakın zamanda ilgili bir soruya verdiğim yanıta da bakmak isteyebilirsiniz .



6

Bir yaklaşıma tahammül etmek istiyorsanız, başka yöntemler de vardır. Örneğin, bir yaklaşım sıralaması gerçek ortancadan (kullanıcı tarafından belirtilen) bir mesafede olan bir değerdir. Örneğin, medyan 0,5 (normalleştirilmiş) sıralamaya sahiptir ve% 10'luk bir hata terimi belirtirseniz, 0,45 ile 0,55 arasında bir cevap istersiniz.

Böyle bir cevap uygunsa, sürgülü veri pencerelerinde çalışabilecek birçok çözüm vardır. Temel fikir, belirli bir boyuttaki verilerin bir örneğini (kabaca 1 / hata terimi) korumak ve bu örnek üzerindeki medyanı hesaplamaktır. Yüksek olasılıkla, girdinin doğasına bakılmaksızın, ortaya çıkan medyanın yukarıda bahsettiğim özellikleri karşıladığı gösterilebilir.

Bu nedenle, ana soru, belirli bir boyuttaki verilerin çalışan bir örneğinin nasıl korunacağıdır ve rezervuar örnekleme olarak bilinen teknik dahil olmak üzere birçok yaklaşım vardır. Örneğin, bu makale: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.7136


4

Bir uzunluk-k veri penceresini sıralanmış bir ikili bağlantı listesi olarak tutarsanız, ikili bir arama (her yeni öğeyi pencereye kaydırılırken eklemek için) ve dairesel bir işaretçi dizisi (hemen silinmesi gerekir), pencerenin her vardiyasında bir öğe eklemek için O (günlük (k)) çabası, pencereden dışarı kaydırılan öğeyi silmek için yalnızca O (1) çaba ve yalnızca O (1) bulma çabası gerekir ortanca (listeye her öğe eklendiğinde veya silindiğinde, bir işaretçiyi ortancaya O (1) zamanında güncelleyebilirsiniz). N uzunluğundaki bir diziyi işlemek için toplam çaba O ((nk) log (k)) <= O (n log (k)) şeklindedir. Bu, şimdiye kadar önerilen diğer yöntemlerden daha iyidir ve bir yaklaşım değildir, kesindir.


1
Sıralı, ikili bağlantılı bir listede ikili aramayı nasıl önereceğinizi açıklayabilir misiniz?
NPE

bir 'bağlantı' listeyi sıralı olarak geçmenizi sağlar; diğeri, öğelerin göründüğü sırayla geçiş yapmanızı sağlar. Bununla birlikte, @aix soruları olarak bunu işaretçilerle nasıl yapacağınız açık değildir.
shabbychef

2
@aix Bence niyetiniz doğru; Ben sadece sıralı iki bağlantılı bir liste değil, endekslenebilir bir atlama listesi gerekir. Fikir, bir elemanın eklenmesine, bir elemanın silinmesine ve medyanın beklenen O (log (n)) zamanında (veya daha iyi) bulunmasına izin veren bir veri yapısına sahip olmaktır.
whuber

3

Bahsettiğiniz gibi, sıralama O(n·log n)bir uzunluk penceresi için olacaktır n. Bu hareketi l=vectorlengthyapmak, toplam maliyeti artıracak başka bir şey ekler O(l·n·log n).

Bunu itmenin en basit yolu, bir pencereden diğerine geçerken hafızadaki son n öğenin sıralı bir listesini tutmaktır. Bir öğeyi sıralı bir listeden / sıralı bir listeye çıkarmak / eklemek, her ikisinin de O(n)maliyetiyle sonuçlanır O(l·n).

pseudocode:

l = length(input)
aidvector = sort(input(1:n))
output(i) = aid(n/2)
for i = n+1:l
    remove input(i-n) from aidvector
    sort aid(n) into aidvector
    output(i) = aid(n/2)


2

Gerçek medyan yerine bir tahminle yaşayabiliyorsanız, Remedian Algoritması (PDF) , düşük depolama gereksinimleri ve iyi tanımlanmış doğruluk ile tek geçiştir.

B bazlı ilaç, b gözlem gruplarının medyanlarını ve daha sonra bu medyanların medyanlarını sadece tek bir tahmin kalana kadar ilerletir. Bu yöntem yalnızca b boyutunda k dizilerine ihtiyaç duyar (burada n = b ^ k) ...


0

Bu RunningStats C ++ Kitaplığını kullandım gömülü bir uygulamada kullandım. Henüz bulduğum en basit koşu istatistikleri kütüphanesi.

Bağlantıdan:

Kod, verilerden bir geçişte standart sapmayı hesaplamak için Knuth ve Welford yönteminin bir uzantısıdır. Benzer bir arayüzle çarpıklık ve basıklık da hesaplar. Verilerden sadece bir geçiş yapılmasına gerek kalmasının yanı sıra, algoritma sayısal olarak kararlı ve doğrudur.


Bu sayfa medyan hakkında bir şey söylüyor mu?
musiphil
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.