В основе работы с пространственными данными в Turf.js лежит модель
GeoJSON, где каждая сущность представлена объектом Feature,
содержащим геометрию и набор атрибутов в properties.
Суммирование атрибутов — базовый механизм аналитики, применяемый для
вычисления статистик по наборам пространственных объектов: суммарной
площади, количества населения, стоимости объектов, длины маршрутов и
любых пользовательских метрик.
В Turf.js отсутствует отдельная универсальная функция «sum attributes», поскольку библиотека ориентирована на композицию примитивов и работу через обход коллекций. Суммирование реализуется через модуль мета-функций и стандартные JavaScript-операции накопления.
Каждый объект GeoJSON имеет структуру:
{
"type": "Feature",
"geometry": { ... },
"properties": {
"value": 10,
"population": 5000
}
}
Суммирование выполняется по одному или нескольким ключам в
properties. Важный принцип: Turf.js не изменяет исходные
данные, а использует обход без мутаций.
Модуль @turf/meta предоставляет набор низкоуровневых
функций для работы с любыми GeoJSON структурами.
Итерация по всем Feature в FeatureCollection:
import { featureEach } from "@turf/meta";
let sum = 0;
featureEach(geojson, (feature) => {
sum += feature.properties.value || 0;
});
Механизм работы:
propertiesИспользуется для обхода только атрибутов без привязки к геометрии:
import { propEach } from "@turf/meta";
let total = 0;
propEach(geojson, (properties) => {
total += properties.value || 0;
});
Различие:
featureEach даёт доступ к геометрии и атрибутамpropEach работает исключительно с атрибутамиХотя координаты редко суммируются напрямую, функция полезна при вычислении производных значений:
import { coordEach } from "@turf/meta";
let coordinateSum = 0;
coordEach(geojson, (coord) => {
coordinateSum += coord[0]; // сумма долгот
});
Наиболее распространённый подход — ручная агрегация:
let total = 0;
for (const feature of geojson.features) {
total += Number(feature.properties.value) || 0;
}
Этот подход:
В реальных данных атрибуты часто содержат строки, null или отсутствующие значения:
import { featureEach } from "@turf/meta";
let total = 0;
featureEach(geojson, (feature) => {
const value = feature.properties.value;
if (typeof value === "number" && !Number.isNaN(value)) {
total += value;
}
});
Обработка типов предотвращает:
Часто требуется суммировать несколько полей одновременно:
import { featureEach } from "@turf/meta";
const sum = {
population: 0,
area: 0,
revenue: 0
};
featureEach(geojson, (feature) => {
const p = feature.properties;
sum.population += p.population || 0;
sum.area += p.area || 0;
sum.revenue += p.revenue || 0;
});
Такой подход используется при построении агрегированных статистик для регионов.
Агрегация часто выполняется с фильтрацией по атрибутам:
import { featureEach } from "@turf/meta";
let total = 0;
featureEach(geojson, (feature) => {
if (feature.properties.type === "urban") {
total += feature.properties.value || 0;
}
});
Условия могут включать:
При анализе полигонов часто требуется вычислить суммарную площадь:
import area from "@turf/area";
import { featureEach } from "@turf/meta";
let totalArea = 0;
featureEach(polygons, (feature) => {
totalArea += area(feature);
});
Особенности:
Для линейных объектов используется length из
Turf.js:
import length from "@turf/length";
import { featureEach } from "@turf/meta";
let totalLength = 0;
featureEach(lines, (feature) => {
totalLength += length(feature, { units: "kilometers" });
});
Применение:
Более сложный сценарий — агрегирование по категориям:
import { featureEach } from "@turf/meta";
const groups = {};
featureEach(geojson, (feature) => {
const key = feature.properties.region;
if (!groups[key]) {
groups[key] = 0;
}
groups[key] += feature.properties.value || 0;
});
Результат — объект агрегированных значений:
JavaScript reduce позволяет выразить суммирование декларативно:
const total = geojson.features.reduce((acc, feature) => {
return acc + (feature.properties.value || 0);
}, 0);
Этот стиль:
Часто данные ограничиваются географически:
import bbox from "@turf/bbox";
import booleanPointInPolygon from "@turf/boolean-point-in-polygon";
const polygon = ...;
let total = 0;
featureEach(points, (feature) => {
if (booleanPointInPolygon(feature, polygon)) {
total += feature.properties.value || 0;
}
});
Используется для:
При работе с тысячами и миллионами объектов важны следующие оптимизации:
propertiesПример оптимизированного варианта:
const features = geojson.features;
let sum = 0;
for (let i = 0; i < features.length; i++) {
sum += features[i].properties.value || 0;
}
Turf.js часто используется как этап обработки перед агрегацией:
import buffer from "@turf/buffer";
import { featureEach } from "@turf/meta";
const buffered = buffer(points, 5, { units: "kilometers" });
let totalArea = 0;
featureEach(buffered, (feature) => {
totalArea += feature.properties.area || 0;
});
Пайплайн:
Суммирование редко используется изолированно. Оно является частью цепочек:
boolean-intersects,
within)buffer,
transform-scale)area, length)Типовой аналитический контур:
featureEach(dataset, (feature) => {
if (feature.properties.category === "A") {
result += feature.properties.value;
}
});
При работе с реальными источниками данных важно учитывать:
Универсальная защита:
const value = Number(feature.properties.value);
if (Number.isFinite(value)) {
sum += value;
}
Сумма часто вычисляется вместе с другими метриками:
let sum = 0;
let count = 0;
featureEach(geojson, (feature) => {
const v = feature.properties.value;
if (typeof v === "number") {
sum += v;
count++;
}
});
const average = sum / count;
Это базовая форма статистического анализа внутри Turf.js-экосистемы.