2013-03-20 4 views
2

У меня есть то, что в конечном итоге составляет большой массив чисел (вытащил из базы данных).Средний размер массива?

Таким образом, это может выглядеть следующим образом: [1,3,1,2,1,3,1,2,3,1,2,3,1,3,1,3,1,1,3,2,3,3,3,3,1,1,1,1,3,2,1]

Кроме этого может быть 50000 номеров вместо нескольких десятков. Самое низкое число всегда будет 1, а самое высокое - 3.

Что мне нужно сделать, это найти какую-то скользящую среднюю, чтобы я мог отображать данные в управляемой линейной диаграмме.

Значит, может быть, среднее число каждых 5-10 точек данных? Просто не уверен, что лучший способ обработать что-то подобное.

ПРИМЕЧАНИЕ: Не требуется получение единого среднего значения. Я ищу, чтобы перевести весь массив в несколько более средних баллов. Таким образом, набор данных в 1000 пунктов может быть разбит на 10 средних чисел.

+1

Как боковое, самое высокое в вашем примере (до редактирования было) нет 3.) Но реальный вопрос заключается в том, насколько точны ваши «средние»? – raina77ow

+2

есть причина, по которой вы не просто выбираете среднее значение непосредственно из базы данных? – mcfinnigan

+0

@mcfinnigan Мне не нужен ни один средний ... Мне нужно несколько усредненных точек данных. Таким образом, набор данных из 1000 номеров может иметь 10 средних баллов. – Shpigford

ответ

4
1.9.3p327 :001 > a = [1,3,1,2,1,3,1,2,3,1,2,3,1,3,1,3,1,1,3,2,3,3,3,3,1,1,1,1,3,2,1] 
=> [1, 3, 1, 2, 1, 3, 1, 2, 3, 1, 2, 3, 1, 3, 1, 3, 1, 1, 3, 2, 3, 3, 3, 3, 1, 1, 1, 1, 3, 2, 1] 
1.9.3p327 :002 > a.each_cons(10).map { |subarray| subarray.reduce(0.0, :+)/subarray.size } 
=> [1.8, 1.9, 1.9, 1.9, 2.0, 2.0, 2.0, 2.0, 1.9, 1.9, 2.0, 2.1, 2.1, 2.3, 2.3, 2.3, 2.1, 2.1, 2.1, 2.1, 2.1, 1.9] 

Это нехорошо с точки зрения производительности. Это O (NM), где N - размер массива, а M - размер окна (в этом случае 10).

UPD: Или вы можете использовать each_slice, если вам нужно «уменьшить» размер массива значительно:

1.9.3p327 :002 > a.each_slice(10).map { |subarray| subarray.reduce(0.0, :+)/subarray.size } 
=> [1.8, 2.0, 2.1, 1.0] 
+1

Для чего нужен OP: «Так, может быть, среднее число каждых 5-10 точек данных?», 'Each_cons' должно быть заменено на' each_slice'. – AGS

+0

В чем разница между функциями 'each_cons' и' each_slice'? 'each_slice', вероятно, то, что мне нужно ... но любопытно, что именно делает' each_cons'. – Shpigford

+1

'each_slice' принимает каждый элемент' n', тогда как 'each_cons' перемещает окно размером' n' вперед, по одному элементу за раз. [Перечислимые документы] (http://ruby-doc.org/core-2.0/Enumerable.html) – AGS

1

Среднего усреднение НЕ такие же, как в среднем в целом. Если вы не требуете большей точности или не требуете подмножеств средних значений, я не рекомендую его.

+0

Это не «среднее значение средних значений» ... оно просто разбивает кучу чисел на несколько средних значений по сравнению с диапазон данных вместо одного среднего. – Shpigford

+0

Тогда ваша идея золотая (усреднение в подмножествах) – fcm

4

Этот срез можно получить непосредственно через базу данных. Ваш механизм базы данных почти наверняка сделает группировку и средний расчет, по крайней мере, на порядок быстрее, чем рубин, кроме того, вы будете передавать гораздо меньше данных по проводнику из своего дБ в вашу программу и значительно уменьшить количество объектов, созданных в вашем ruby для представления набора результатов.

Итак, если ваш оригинальный запрос выглядел примерно так (в Postgresql):

select value from mytable; 

Вы можете изменить его, чтобы производить в среднем за каждые десять пунктов, как это:

select avg(value) as chunk_avg, row/10 as chunk 
from 
    (select value, row_number() over() - 1 as row 
    from mytable) x 
group by chunk 
order by chunk; 

SqlFiddle

Если вы не хотите, чтобы номер фрагмента в результате, вы можете обернуть это в другой внешний выбор, который просто проекты chunk_avg, или опустите поле chunk в форму select и буквально замените chunk на row/10 в статьях group by и order by.

Смежные вопросы