Усреднение близко расположенных точек в рамках допуска¶
Покажем, как можно сократить количество точек на графике, оставив только те, которые отличаются от остальных по какому-то критерию.
Исходные данные¶
Воспользуемся функцией из файла peaks.jl
, которая создаст нам гладкую поверхность с несколькими выступами в интервале [-3,3], [-3,3]. Добавим к данным шума немного по оси Z. Теперь облако точек уже не лежит на одной поверхности, а разбросано вокруг нее.
gr( format=:png ) # Обратите внимание, теперь все графики, в рамках
# текущей рабочей сессии, будут выводиться в PNG
include( "$(@__DIR__)/peaks.jl" );
xy = rand(10000, 2) .* 6 .- 3;
z = peaks.( xy[:,1], xy[:,2] ) .+ 0.5 .- rand(10000,1);
A = [xy z]
scatter( A[:,1], A[:,2], A[:,3], camera=(45, 20), ms=2, markerstrokewidth=0.1, leg=false )
Восстановление гладкой поверхности¶
Внутри этого облака точек мы поищем те точки, которые можно было бы объединить по следующим признакам:
- расстояние между точками не превышает
tol
, - не интересуемся осью Z, сравниваем только X и Y.
tol = 0.33;
Чтобы выделить идентичные области, огрубим исходный набор данных, округлив все координаты каждой точки до целого числа, предварительно умножив на 1/tol
.
aA = round.( (1/tol) .* A[:,1:2], digits=0);
Наша матрица теперь состоит из большого количества групп векторов с идентичными значениями. Как нам их сгрупипровать? Можно поэлементно сравнивать векторы между собой, но более короткий путь.
Эту операцию можно выплонить при помощи функции groupslices
из библиотеки GroupSlices
(при необходимости, чтобы ее поставить, раскомментируйте и выполните следующую ячейку):
#]add GroupSlices
using GroupSlices
C = groupslices( aA, dims=1 );
Функция groupslices
для каждой строки r матрицы возвращает индекс *первой встреченной строчки, идентичной r.
Усредним точки в каждой подгруппе.
using Statistics
avgA = [ mean( A[C .== c, :], dims=1) for c in unique( C ) ]
avgA = vcat( avgA... ); # Мы получили матрицу из матриц; осуществим вертикальную конкатенацию строчек
Теперь мы можем построить график из усредненных точек, отметив для себя что хотя набор данных и не стал структурированным, но мы избавились от вариативности по оси Z, сохранив общий вид исходных данных.
scatter( A[:,1], A[:,2], A[:,3], camera=(45, 20), ms=2, markerstrokewidth=0.1, leg=false )
scatter!( avgA[:,1], avgA[:,2], avgA[:,3], color=:red, ms=3, legend=false )
Отдельные области можно увидеть, раскрасив их следующим образом:
scatter( A[:,1], A[:,2], A[:,3], camera=(45, 20), ms=2, markerstrokewidth=0.1, leg=false, zcolor=C./maximum(C), c=:prism )
scatter!( avgA[:,1], avgA[:,2], avgA[:,3], color=:white, ms=3, legend=false, camera=(0,90) )
Заключение¶
Мы отфильтровали зашумленную функцию, отобрав некоторые уникальные точки. В их отборе мы опирались на допустимую близость между опорными точками по осям X и Y.