Загрузка данных из файлов

Любая визуализация в Kepler.gl начинается с импорта данных. Библиотека предоставляет несколько механизмов загрузки наборов данных, поддерживает различные форматы файлов и автоматически выполняет анализ структуры таблиц для дальнейшего отображения на карте.

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

Основные поддерживаемые форматы:

  • CSV
  • GeoJSON
  • JSON
  • ZIP-архивы с пространственными данными
  • Данные в формате массива объектов JavaScript
  • Таблицы, загруженные через API
  • Бинарные форматы через экосистему loaders.gl

Архитектура загрузки данных

После импорта файла Kepler.gl выполняет несколько этапов обработки:

  1. Чтение содержимого файла.
  2. Определение формата данных.
  3. Разбор структуры.
  4. Поиск географических координат.
  5. Создание внутреннего объекта Dataset.
  6. Передача набора данных в состояние приложения.

Упрощённая схема выглядит следующим образом:

Файл
  ↓
Parser
  ↓
Dataset
  ↓
Kepler.gl Store
  ↓
Map Layers

После завершения загрузки данные становятся частью состояния Redux и могут использоваться всеми компонентами карты.


Установка зависимостей

Для работы с загрузкой данных необходимо установить Kepler.gl и его зависимости.

npm install kepler.gl

Для React-проекта обычно дополнительно используются:

npm install react react-dom redux react-redux

Пример базового подключения:

import KeplerGl from 'kepler.gl';

function App() {
  return (
    <KeplerGl
      id="map"
      width={1200}
      height={800}
    />
  );
}

Механизм addDataToMap

Основной способ программной загрузки данных — действие addDataToMap.

Импорт:

import { addDataToMap } from 'kepler.gl/actions';

Это действие принимает объект с описанием набора данных и параметрами отображения.

Общая структура:

dispatch(
  addDataToMap({
    datasets: dataset
  })
);

После вызова Kepler.gl автоматически создаёт набор данных и отображает его на карте.


Структура Dataset

Минимальная структура набора данных выглядит следующим образом:

const dataset = {
  info: {
    label: 'Cities'
  },
  data: {
    fields: [],
    rows: []
  }
};

Поле info

Содержит служебную информацию.

info: {
  label: 'Cities',
  id: 'cities_dataset'
}

Параметры:

Поле Назначение
label Отображаемое имя
id Уникальный идентификатор

Поле fields

Описывает структуру столбцов.

fields: [
  {
    name: 'city',
    type: 'string'
  },
  {
    name: 'latitude',
    type: 'real'
  },
  {
    name: 'longitude',
    type: 'real'
  }
]

Наиболее распространённые типы:

Тип Описание
string Строка
integer Целое число
real Число с плавающей точкой
boolean Логическое значение
timestamp Время
date Дата
geojson Геометрия

Поле rows

Содержит сами данные.

rows: [
  ['Almaty', 43.2389, 76.8897],
  ['Astana', 51.1694, 71.4491]
]

Порядок значений должен соответствовать порядку полей в массиве fields.


Загрузка CSV-файла

CSV является наиболее распространённым форматом данных для Kepler.gl.

Пример файла:

city,latitude,longitude,population
Almaty,43.2389,76.8897,2000000
Astana,51.1694,71.4491,1300000

Загрузка через выбор файла пользователем:

<input
  type="file"
  onCha nge={handleFile}
/>

Обработчик:

function handleFile(event) {
  const file = event.target.files[0];

  const reader = new FileReader();

  reader.onl oad = function(e) {
    const csvText = e.target.result;

    dispatch(
      addDataToMap({
        datasets: csvText
      })
    );
  };

  reader.readAsText(file);
}

Kepler.gl самостоятельно определит формат CSV и создаст набор данных.


Использование drag-and-drop

Во встроенном интерфейсе Kepler.gl присутствует поддержка перетаскивания файлов.

Пользователь может:

  • перенести CSV-файл;
  • перенести GeoJSON;
  • перенести ZIP-архив;
  • загрузить несколько файлов одновременно.

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


Загрузка GeoJSON

GeoJSON является стандартом представления геопространственных объектов.

Пример:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "Almaty"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          76.8897,
          43.2389
        ]
      }
    }
  ]
}

Загрузка:

fetch('/data/cities.geojson')
  .then(response => response.json())
  .then(data => {
    dispatch(
      addDataToMap({
        datasets: data
      })
    );
  });

После обработки Kepler.gl автоматически создаст слой на основе геометрии объектов.


Загрузка JSON

Если данные представлены обычным JSON-массивом:

[
  {
    "city": "Almaty",
    "lat": 43.2389,
    "lng": 76.8897
  },
  {
    "city": "Astana",
    "lat": 51.1694,
    "lng": 71.4491
  }
]

Можно загрузить их следующим образом:

fetch('/cities.json')
  .then(response => response.json())
  .then(data => {
    dispatch(
      addDataToMap({
        datasets: data
      })
    );
  });

Загрузка данных через API

На практике данные часто поступают от серверного API.

Пример:

async function loadCities() {
  const response = await fetch(
    'https://api.example.com/cities'
  );

  const data = await response.json();

  dispatch(
    addDataToMap({
      datasets: data
    })
  );
}

После получения ответа данные сразу становятся доступными в карте.


Загрузка нескольких наборов данных

Kepler.gl способен одновременно работать с несколькими Dataset.

Пример:

dispatch(
  addDataToMap({
    datasets: [
      datasetCities,
      datasetRoads,
      datasetStations
    ]
  })
);

В результате каждый набор данных отображается независимо и может использовать собственные слои.


Настройка имени набора данных

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

const dataset = {
  info: {
    label: 'Weather Stations'
  },
  data: {
    fields,
    rows
  }
};

Название отображается:

  • в списке наборов данных;
  • в настройках слоёв;
  • в фильтрах;
  • в панели анализа.

Автоматическое определение координат

Во время загрузки Kepler.gl анализирует названия столбцов.

Типичные имена координат:

lat
latitude
lng
lon
longitude

При обнаружении подобных полей система предлагает создать слой точек автоматически.

Например:

id,latitude,longitude
1,43.2389,76.8897
2,51.1694,71.4491

После импорта карта сразу получает Point Layer.


Ручная настройка географических полей

Если столбцы имеют нестандартные названия:

id,x_coord,y_coord
1,76.8897,43.2389

Координаты можно указать вручную в настройках слоя.

Программный вариант:

layerConfig: {
  columns: {
    lat: 'y_coord',
    lng: 'x_coord'
  }
}

Загрузка больших файлов

При работе с крупными наборами данных необходимо учитывать объём памяти браузера.

Проблемы:

  • длительная обработка;
  • рост потребления RAM;
  • снижение FPS карты;
  • задержки интерфейса.

Рекомендуемые подходы:

  • использовать бинарные форматы;
  • предварительно фильтровать данные на сервере;
  • разбивать файлы на части;
  • уменьшать количество колонок.

Использование loaders.gl

Kepler.gl тесно интегрирован с экосистемой loaders.gl.

Установка:

npm install @loaders.gl/core

Пример:

import { load } from '@loaders.gl/core';

Загрузка файла:

const data = await load(
  '/data/file.geojson'
);

После получения результата данные передаются в Kepler.gl.


Загрузка ZIP-архивов

Kepler.gl поддерживает архивированные пространственные данные.

Часто используются:

  • ZIP с Shapefile;
  • ZIP с GeoJSON;
  • архивы пространственных наборов данных.

Пользователь может просто выбрать архив через интерфейс загрузки.

Внутренние загрузчики автоматически распакуют содержимое и преобразуют его в Dataset.


Обработка ошибок загрузки

При работе с внешними файлами необходимо контролировать возможные ошибки.

Пример:

try {
  const response = await fetch('/data.csv');

  if (!response.ok) {
    throw new Error('Loading error');
  }

  const data = await response.text();

  dispatch(
    addDataToMap({
      datasets: data
    })
  );
}
catch(error) {
  console.error(error);
}

Основные причины ошибок:

  • повреждённый файл;
  • некорректный JSON;
  • неправильная кодировка;
  • отсутствие доступа к ресурсу;
  • сетевые проблемы.

Асинхронная загрузка данных

Практически все операции импорта являются асинхронными.

Использование async/await делает код более удобным:

async function loadDataset() {
  const response = await fetch(
    '/dataset.geojson'
  );

  const dataset = await response.json();

  dispatch(
    addDataToMap({
      datasets: dataset
    })
  );
}

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


Предварительная обработка данных перед загрузкой

Нередко данные требуют очистки ещё до передачи в Kepler.gl.

Пример фильтрации:

const filtered = rows.filter(
  row => row.population > 100000
);

Преобразование значений:

const normalized = rows.map(row => ({
  ...row,
  population: Number(row.population)
}));

Удаление пустых координат:

const cleanRows = rows.filter(
  row =>
    row.latitude !== null &&
    row.longitude !== null
);

Подготовленные данные работают быстрее и обеспечивают более корректную визуализацию.


Загрузка данных при инициализации приложения

Часто карта должна отображать данные сразу после открытия страницы.

Пример для React:

useEffect(() => {
  loadDataset();
}, []);

Функция загрузки:

async function loadDataset() {
  const response = await fetch(
    '/cities.geojson'
  );

  const data = await response.json();

  dispatch(
    addDataToMap({
      datasets: data
    })
  );
}

В результате карта будет заполнена данными сразу после монтирования компонента.


Совмещение данных и конфигурации карты

Во время загрузки можно одновременно передавать настройки визуализации.

Пример:

dispatch(
  addDataToMap({
    datasets: dataset,
    options: {
      centerMap: true,
      readOnly: false
    }
  })
);

Параметр centerMap автоматически перемещает карту к загруженным объектам.

Параметр readOnly определяет возможность изменения настроек пользователем.


Практические рекомендации

Для CSV-файлов

  • использовать UTF-8;
  • избегать смешанных типов данных в одном столбце;
  • использовать понятные названия колонок.

Для GeoJSON

  • хранить геометрию в формате WGS84;
  • избегать чрезмерно детализированных полигонов;
  • проверять корректность структуры FeatureCollection.

Для API

  • отдавать только необходимые поля;
  • использовать пагинацию для больших объёмов;
  • выполнять агрегацию на сервере.

Для крупных проектов

  • хранить данные отдельно от конфигурации карты;
  • применять ленивую загрузку;
  • использовать кеширование запросов;
  • предварительно валидировать входящие наборы данных;
  • минимизировать объём передаваемой геометрии;
  • контролировать объём памяти браузера при работе с многомиллионными наборами записей.