Взвешенная агрегация

В пространственном анализе часто возникает задача объединения набора геоданных в агрегированные показатели, где каждая точка или объект имеет различную значимость. Взвешенная агрегация в геоинформационных вычислениях подразумевает учет дополнительного числового параметра — веса, влияющего на вклад каждого объекта в итоговый результат. В Turf.js подобные операции реализуются через комбинацию базовых геометрических функций и пользовательских вычислений над GeoJSON-структурами.

Представление данных и роль веса

В Turf.js все пространственные данные представлены в формате GeoJSON. Типичная структура включает:

  • Feature<Point> — точечные объекты
  • Feature<Polygon> — полигональные области
  • FeatureCollection — набор объектов

Вес обычно хранится в свойствах объекта:

{
  type: "Feature",
  geometry: {
    type: "Point",
    coordinates: [71.4304, 51.1282]
  },
  properties: {
    value: 120,
    weight: 0.7
  }
}

Поле weight не является стандартным для Turf.js, но широко используется как пользовательская метрика для агрегирования значений.

Базовый подход к взвешенной агрегации

В Turf.js отсутствует универсальная встроенная функция взвешенного среднего, поэтому применяется комбинация операций:

  • фильтрация пространственных объектов
  • сбор значений
  • вычисление суммы произведений значений на веса
  • нормализация результата

Формально:

{x} =

где:

  • ( x_i ) — значение свойства объекта
  • ( w_i ) — вес
  • ( n ) — количество объектов

Пространственная фильтрация перед агрегацией

Часто агрегация выполняется внутри геометрической области. Для этого используется @turf/within или @turf/booleanPointInPolygon в сочетании с перебором коллекций.

Пример логики:

import * as turf from "@turf/turf";

const points = turf.featureCollection([
  turf.point([71.4, 51.1], { value: 10, weight: 0.2 }),
  turf.point([71.5, 51.2], { value: 20, weight: 0.5 }),
  turf.point([71.6, 51.3], { value: 30, weight: 1.0 })
]);

const polygon = turf.polygon([[
  [71.3, 51.0],
  [71.7, 51.0],
  [71.7, 51.4],
  [71.3, 51.4],
  [71.3, 51.0]
]]);

Фильтрация точек по полигону:

const inside = points.features.filter(pt =>
  turf.booleanPointInPolygon(pt, polygon)
);

Реализация взвешенного среднего

После отбора объектов выполняется агрегация:

let weightedSum = 0;
let weightTotal = 0;

inside.forEach(f => {
  const w = f.properties.weight ?? 1;
  const v = f.properties.value ?? 0;

  weightedSum += v * w;
  weightTotal += w;
});

const result = weightTotal === 0 ? 0 : weightedSum / weightTotal;

Такой подход используется для вычисления:

  • средней температуры в регионе
  • плотности населения
  • средней стоимости недвижимости с учетом значимости объектов

Использование turf.collect для группировки значений

Функция turf.collect применяется для сбора свойств точек, попадающих в полигон, и формирования массива значений внутри полигонального объекта.

const collected = turf.collect(
  polygon,
  points,
  "value",
  "values"
);

Результат:

{
  type: "Feature",
  properties: {
    values: [10, 20, 30]
  }
}

После этого взвешивание выполняется вручную:

const values = collected.features[0].properties.values;

const avg = values.reduce((acc, v) => acc + v, 0) / values.length;

Для взвешенной версии необходимо параллельно собирать веса через дополнительную структуру или расширение данных.

Взвешенная агрегация через редукцию FeatureCollection

Обобщенный паттерн агрегации в Turf.js строится на reduce:

const aggregated = points.features.reduce(
  (acc, f) => {
    const w = f.properties.weight ?? 1;
    const v = f.properties.value ?? 0;

    acc.sum += v * w;
    acc.weight += w;

    return acc;
  },
  { sum: 0, weight: 0 }
);

const weightedAverage = aggregated.sum / aggregated.weight;

Такой подход масштабируется на:

  • десятки тысяч объектов
  • потоковую обработку данных
  • предварительную агрегацию перед визуализацией

Пространственная агрегация по сетке

Часто данные агрегируются не по полигонам, а по регулярной сетке. Turf.js предоставляет squareGrid и hexGrid.

const bbox = [71.0, 51.0, 72.0, 52.0];

const grid = turf.squareGrid(bbox, 0.1);

Далее каждая ячейка заполняется точками:

const enriched = grid.features.map(cell => {
  const pts = points.features.filter(p =>
    turf.booleanPointInPolygon(p, cell)
  );

  let sum = 0;
  let wsum = 0;

  pts.forEach(p => {
    const w = p.properties.weight || 1;
    sum += p.properties.value * w;
    wsum += w;
  });

  cell.properties.avg = wsum ? sum / wsum : null;
  return cell;
});

Такой подход используется для построения heatmap-подобных визуализаций.

Взвешенные центроиды и смещение геометрии

Хотя Turf.js предоставляет turf.centroid, он вычисляет геометрический центр без учета значений свойств. Для взвешенного центра применяется пользовательская формула:

x_c = , y_c =

Реализация:

let xSum = 0;
let ySum = 0;
let wSum = 0;

points.features.forEach(f => {
  const [x, y] = f.geometry.coordinates;
  const w = f.properties.weight ?? 1;

  xSum += x * w;
  ySum += y * w;
  wSum += w;
});

const weightedCentroid = [
  xSum / wSum,
  ySum / wSum
];

Такой центр используется для:

  • смещения маркеров кластеров
  • определения “центра массы” объектов
  • анализа концентрации событий

Комбинация с кластеризацией

В Turf.js присутствует @turf/clusters-kmeans, который группирует точки по пространственной близости. Взвешивание добавляется после кластеризации:

const clustered = turf.clustersKmeans(points, {
  numberOfClusters: 3
});

const clusterStats = {};

clustered.features.forEach(f => {
  const cluster = f.properties.cluster;
  const w = f.properties.weight || 1;
  const v = f.properties.value || 0;

  if (!clusterStats[cluster]) {
    clusterStats[cluster] = { sum: 0, wsum: 0 };
  }

  clusterStats[cluster].sum += v * w;
  clusterStats[cluster].wsum += w;
});

Результат позволяет анализировать не только географическое распределение, но и значимость объектов внутри групп.

Взвешенная плотность и сглаживание

Для непрерывных пространственных полей применяется kernel density analysis через @turf/point-grid и последующую интерполяцию. Взвешивание усиливает вклад более значимых точек, формируя сглаженные поверхности.

Общая схема:

  • генерация сетки
  • расчет расстояний до точек
  • применение веса к функции влияния
  • суммирование вкладов

Такой подход используется в:

  • анализе преступности
  • моделировании транспортной нагрузки
  • распределении загрязнений воздуха

Объединение агрегационных подходов

В реальных задачах применяется комбинация методов:

  • предварительная кластеризация
  • агрегация внутри сетки
  • взвешенное среднее по атрибутам
  • расчет производных метрик (дисперсия, плотность, медиана)

В результате формируются многослойные пространственные модели, где каждая ячейка или кластер содержит набор статистических характеристик, основанных на взвешенных вычислениях над GeoJSON-структурами Turf.js.