Что такое визуализация географических данных

Анализируем данные с помощью визуализации: рисуем поверх Google Maps

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Привет, я Катя, системный аналитик в Ozon. Одна из первых задач, которую мне поручили здесь — проверить качество географических данных. Формально эта задача больше относится к анализу данных, чем к системному анализу. Но меня она очень заинтересовала, ведь требовался не только анализ, но и исследование и, по возможности, реализация решения, а для меня это самое интересное в работе.

Впереди меня ждала RnD-задача с исследованием картографических форматов, рисованием поверх Google Maps и реализацией скрипта на Python. Как я боролась с визуализацией картографических данных, расскажу в этой статье.

Как работает определение населённого пункта

У нас в Ozon есть сервис, который по переданной координате определяет населённый пункт. Это своего рода обратное геокодирование.

Время от времени от коллег из поддержки нам прилетали сообщения о том, что сервис некорректно определяет населённый пункт. Например, на картах Яндекса координаты соответствуют Алматы, а наш сервис считает, что это Баганашыл. Забегая вперед, покажу, как выглядели данные по Алматы в нашем сервисе.

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Пришло время проверить корректность географических данных, хранящихся в нашей системе.

Данные для нашего сервиса мы храним в PostrgreSQL с расширением PostGIS, которое позволяет работать с географическими объектами. Для определения населенного пункта нужны: его название, координата центра и геометрия, обозначающая его границы (полигон или мультиполигон).

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

Определение населённого пункта по вхождению точки в геометрию является самым точным методом, но есть важная деталь: данные должны быть корректными. В нашем случае именно корректность данных по полигонам стала проблемой. Эти данные копились в системе в течение всей её жизни. Что-то вносили вручную, что-то унаследовано из других систем,

Раз речь о картах — наглядной информации, то для проверки корректности данных мы решили их визуализировать. Задачей было нанести полигоны и координаты центров городов поверх реальной карты и визуально оценить, насколько всё хорошо или плохо.

Как импортировать географические данные

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

Такая возможность есть у обоих «главных» картографических сервисов — Google Maps и Яндекс.Карт.

К слову, лично мне больше понравился импорт Google Maps: интуитивно понятнее, подробнее сообщает об ошибках, штатно позволяет загружать координаты точек без формирования CSV-файла по жёсткому шаблону.

И Google Maps, и Яндекс.Карты позволяют с помощью CSV-файла отобразить на карте объекты по их координатам. Однако, чтобы загрузить более сложную геометрию (полигоны, мультиполигоны, линии), нужно иметь файл специфического картографического формата.

Google Maps поддерживает импорт в следующих форматах:

CSV и XLSX — для отображения координат точек,

GPX — для маршрутов,

KML — для любых географических объектов.

У Яндекс.Карт похожий список. Разница лишь в том, что нет GPX, но есть GeoJSON, который по назначению аналогичен KML.

Мой выбор пал на формат KML.

Keyhole Markup Language

Основная причина, по которой я выбрала KML для импорта данных на карты, заключалась в том, что этот формат поддерживают и Google, и Яндекс. Правда, как позже показала практика, бывают файлы с полигонами, которые отображаются на Google Maps, но не видны на Яндекс.Картах (но тогда мне ещё только предстояло это выяснить).

Ещё KML — это язык разметки на основе XML, так что я подумала, что сформировать такой файл будет не очень сложно.

У KML много возможностей — он даже позволяет отрисовывать 3D-объекты. Для решения моей задачи оказалось достаточно пяти элементов:

Placemark — объект, позволяющий задавать геометрию (от координаты точки до мультиполигонов).

Multigeometry — контейнер для нескольких геометрических примитивов, связанных с одним и тем же географическим объектом (например, для координаты центра и полигона).

Polygon — многоугольник области; может дополнительно содержать внутреннюю вырезанную область. Мультиполигоны для отображения разбиваются на полигоны.

Point — географическое местоположение, определяемое долготой и широтой. Координаты следуют в таком порядке: сначала долгота, потом широта.

Style — стиль представления геометрии (например, цвет).

Пример структуры файла для отображения одного объекта, состоящего из точки и полигона:

Финишная прямая: от KML к отображению своих объектов на карте

Файл из тысяч элементов не хочется формировать вручную. С генерацией KML-файлов мне помогла Python-библиотека pyKML.

Я написала небольшой скрипт: на вход он принимает XLSX-файл с данными о географических объектах. Структура файла – четыре колонки: наименование, описание, координата точки, геометрия в текстовом формате WKT (может быть пустой). На выходе формируется KML-файл, который можно использовать для отображения своих объектов на картах.

На всякий случай предупрежу: у Google Maps есть ограничение по количеству импортируемых объектов в 2000 штук. Если нужно отобразить больше, то придётся сделать несколько файлов.

Помните, как выглядел Алматы на карте в начале статьи? Несколько точек и только одна из них принадлежала непосредственно городу Алматы, остальные являлись районами, улицами, парками, в общем, не являлись населенными пунктами. Имея дело с такими данными, наш сервис в большинстве случаев ошибался (у Алматы не было полигона, поэтому алгоритм находил не сам город, а ближайшую точку, которая по факту городом не является).

А вот так Алматы преобразился после обновления данных. Теперь есть полигон и можно быть уверенными, что всё множество точек, входящих в границы города, будет определяться правильно. Такая визуализация помогает увидеть проблемные места и убедиться в корректности данных после обновления.

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Когда всё-таки звать разработчиков для помощи

Google Maps предоставляет отличные возможности для отображения географических данных без каких-либо серьёзных дополнительных манипуляций. Для визуализации в виде «было — стало» сервис подходит отлично, на мой взгляд: можно наглядно убедиться в корректности географических данных.

Когда может не подойти такой подход, и потребуется привлекать тяжёлую артиллерию— разработчиков? Предположим, у вас есть данные о движении грозовых фронтов, и вы хотите показывать их пользователю в режиме реального времени. В этом случае импорт файлов на карту вручную не подойдёт. Однако предполагаю, что формирование KML-файлов для решения этой задачи тоже может пригодиться: вы сможете встроить в своё приложение карту и отрисовывать данные уже программным способом.

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

И конечно, желаю вам качественных данных и успехов в их визуализации!

Ссылки вдогонку

pyKML: Python-библиотека для формирования KML-файлов

WKT: формат представления векторной геометрии и описания систем координат

xslx2kml: мой скрипт для создания KML-файлов на основе XLSX-файлов с данными о географических объектах

Источник

Введение в визуализацию географических данных

Дата публикации May 19, 2018

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Меня всегда очень впечатляли цифры, которым удается объединить данные с географической информацией. Это одни из самых красивых примеров визуализации данных, о которых я только могу подумать, и информация, которую вы можете увидеть одним взглядом, поразительна.

Эти виды фигур называются картограммами и в соответствии сWikiопределяются как:

Тематическая карта (-ы), в которых области заштрихованы или структурированы пропорционально измерению статистической переменной, отображаемой на карте, такой как плотность населения или доход на душу населения

Думайте о них как о тепловых картах, которые принимают во внимание географические границы.

Мы можем сделать картограммы, используя сюжетную библиотеку.

Начнем с простого примера. Мы импортируем следующим образом:

Мы хотим создать переменную «data», которую мы передадим в метод go.Figure () для генерации картограммы.

Давайте начнем с карты большого мира!

Мы определяем переменную data следующим образом:

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

Мы генерируем изображение с:

и получить карту мира. Обратите внимание, когда мы наводим указатель мыши на страну, мы получаем ее имя и присвоенное значение.

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

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

Используя данные изВсемирный отчет о счастье 2017 годамы можем создать эту фигуру, используя код ниже

сгенерировать следующий рисунок. Без какой-либо потребности в статистическом анализе мы можем с уверенностью сказать, что некоторые из самых счастливых стран находятся в Европе и Северной Америке, в то время как некоторые из наименее счастливых стран сосредоточены в Африке. Это сила географической визуализации.

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Теперь давайте немного углубимся в визуализацию Соединенных Штатов.

Сначала мы изменим переменную «data», чтобы locationMode определял американские штаты. Затем мы добавляем переменную «layout», которая позволяет нам настраивать определенные аспекты карты. В этом случае мы говорим карте сосредоточиться на Соединенных Штатах, а не показывать весь мир, который используется по умолчанию. Если вы хотите, вы также можете сосредоточиться на Азии, Европе, Африке, Северной Америке или Южной Америке.

Собрав все воедино, мы присваиваем значения Аризоне, Калифорнии и Вермонту с помощью следующего кода:

чтобы получить эту карту:

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Теперь мы можем начать делать довольно забавные вещи.

Хорошо известно, что в мире наблюдается быстрое сокращение популяции пчел. Это ужасно, потому что это положит конец прекрасным завтракам с мёдом и орехами. Мы можем взять в свои руки число пчелиных семей в каждом штате и использовать наши графики для умений, чтобы увидеть, в каких штатах больше всего пчелиных семей.

Похоже, что в Северной Дакоте больше всего колоний, следующих за Калифорнией, с большим количеством возможностей для улучшения в остальной части страны. Нам также не хватает некоторых данных по Аляске и нескольким штатам в правом верхнем углу, но это ограничение этого набора данных.

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Мы коснулись счастья и пчелиных семей. Теперь все, что осталось, это безработица.

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

Каждый округ может быть однозначно идентифицирован 5-значным номером FIP.

Мы начинаем с нашего импорта и замечаем, что на этот раз мы импортируем plotly.figure_factory

Далее мы читаем в цифрах FIP, а также процент безработицы

Поскольку существует множество различных значений безработицы, и мы не хотим, чтобы наша цветовая шкала пыталась представить 1000 различных значений, мы ограничиваем ее только 12 цветами с помощью следующего

и передать все эти аргументы в наш метод choropleth

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Ух какая красивая карта!

Используя такой график, мы можем быстро определить районы с повышенным уровнем безработицы (обведены красным).

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

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

Надеюсь, вам понравилось это краткое введение в визуализацию географических данных. Дайте мне знать, если у вас есть какие-либо вопросы, и если у вас есть примеры интересных визуализаций географических данных, которыми вы хотели бы поделиться.

Источник

Визуализация и анализ географических данных на языке R

Внимание: разделы курса по пространственной статистике c октября 2021 г. переехали в новый репозиторий: https://tsamsonov.github.io/r-spatstat-course

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

Программное обеспечение

Для успешного прохождения курса на вашем компьютере должно быть установлено следующее программное обеспечение:

Выбирайте инсталлятор, соответствующий вашей операционной системе. Обратите внимание на то, что RStudio не будет работать, пока вы не установите базовые библиотеки языка R. Поэтому обе вышеуказанные компоненты ПО обязательны для установки.

Установка и подключение пакетов

Наиболее часто используются два способа установки пакетов в RStudio.

Во-первых, вы можете сделать это в графическом интерфесе, нажав кнопку Install на панели Packages (по умолчанию эта панель расположена в нижней правой четверти окна программы). В появившемся окне введите название пакета и нажмите Install:

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Рис. 0.1: Установка пакета

Никогда не включайте команду install.packages() в тело скрипта. Это приведет к тому, что каждый раз при запуске программы среда RStudio будет пытаться заново установить пакет, который уже установлен. Запускайте эту функцию только из консоли.

Выполнение программного кода

, Существует несколько способов выполнения исходного кода:

Команды Source и Ctrl + Alt + Enter могут не сработать, если у вас не установлена рабочая директория, или если в пути к рабочей директории содержатся кириллические символы (не актуально для Windows 10+, macOS и Linux, которые являются системами, основанными на кодировке Unicode).

Существует также ряд дополнительных опций выполнения кода, которые вы можете найти в меню Code > Run Region.

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

Установка рабочей директории

Вы можете открывать и сохранять любые поддерживаемые файлы в R, указывая полный системный путь к файлу. Например, так может выглядеть открытие и сохранение таблицы в формате CSV на компьютере Mac:

Однако, если вам требуется открыть или сохранить несколько файлов (и не только данных, но и графиков, карт и т.п.), программа будет выглядеть громоздко. К тому же, прописывать каждый раз полный путь достаточно утомительно и неприятно (даже путем копирования и вставки), а главное — может привести к ошибкам.

Как видно, мы добавили дополнительную строчку кода, но сэкономили на длине двух других строк. При увеличении количества обращений к файлам польза домашней директории будет возрастать. При этом вы можете открывать и сохранять файлы в поддиректориях, наддиректориях и соседних директориях, используя синтаксис, стандартный для большинства операционных систем:

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

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

К сожалению, не существует надежного программного способа сказать среде выполнения R, что в качестве домашей директории следует использовать директорию в которой лежит сам скрипт (что, вообще говоря, было бы крайне удобно). Возможно, в будущем разработчики языка добавят такую полезную функцию. Однако, если для работы с R вы пользуетесь средой RStudio, задача может быть решена путем использования проектов. Подробнее читайте здесь.

Диагностические функции

В R существует ряд диагностических функций, которые позволяют узнавать техническую информацию об объектах и переменных. Эти функции полезны, когда необходимо понять, какого типа, размера и содержания данные хранятся в той или иной переменной. Нижеприведенный список функций не являются исчерпывающим, но охватывает часто употребляемые функции:

ФункцияНазначение
class()Класс (тип данных или структура данных) объекта
attr()Атрибуты объекта
str()Компактное представление внутренней структуры объекта.
names()Названия элементов объекта
colnames()Названия колонок фрейма данных или матрицы
rownames()Названия строк фрейма данных или матрицы
mode()Режим хранения объекта.
length()Размер (длина) объекта.
dim()Измерение объекта.

Помимо этого, часто используются следующие функции, имеющие отношение не к конкретным объектам, а к параметрам работы текущей сессии:

ФункцияНазначение
sessionInfo()Информация о текущей сессии R и подключенных пакетах.
gc()Информация об объеме памяти, занимаемой текущей сессией R (находящейся под управлением сборщика мусора).
options()Получение и установка параметров среды.
getwd()Получение текущей рабочей директории
setwd()Установка текущей рабочей директории
par()Получение и установка графических параметров

Получение справки

Правильно оформленная функция R содержит документированное описание ее параметров и правил использования. Справку можно получить несколькими способами:

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Рис. 0.2: Справка по функции write_xlsx

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Рис. 0.3: Справочные материалы по функциям aggregate из установленных пакетов

Во многих пакетах есть также подробная документация с примерами использования функций в виде руководств и так называемых виньеток (vignettes), которые представляют из себя расширенные руководства (статьи) по использованию пакета. С документацией пакета можно ознакомиться, щелкнув на его названии на вкладке Packages и перейдя по ссылке User guides, package vignettes and other documentation:

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Рис. 0.4: Документация пакета sf

Комментарии

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

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

Прервать комментарий и написать справа от него исполняемый код нельзя

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

Для быстрой вставки комментария, обозначающего новый раздел программы, воспользуйтесь командой меню Code > Insert Section или клавиатурным сочетанием Ctrl + Shift + R ( Cmd + Shift + R для OS X)

Стандарт оформления кода на R

Очень важно сразу же приучить себя грамотно, структурированно и красиво оформлять код на языке R. Это существенно облегчит чтение и понимание ваших программ не только вами, но и другими пользователями и разработчиками. Помимо вышеуказанных рекомендаций по написанию комментариев существует также определенное количество хорошо зарекомендовавших себя и широко используемых практик оформления кода. Эти практики есть в каждом языке программирования и их можно найти в литературе (и в Интернете) в виде негласных сводов правил (style guides).

В частности, одним из полезных для изучения является стандарт tidyverse, систематизированный Хэдли Уикхемом — одним из ведущих идеологов развития языка R и его библиотек.

Стандарт оформления кода иногда также называют стилем программирования. Однако под стилем программирования традиционно понимают все же фундаментальный подход (парадигму) к построению программ: процедурный, функциональный, логический, объектно-ориентированный стиль и некоторые другие.

К числу негласных правил оформления кода на R можно отнести следующие:

Зарезервированные слова

СловоНазначение
ifУсловный оператор ЕСЛИ
elseУсловный оператор ИНАЧЕ
repeatЦикл без внешнего условия
whileЦикл “пока верно условие, повторять”
functionФункция
forЦикл “пройти по элементам последовательности”
inОператор вхождения в множество
nextПереход на новую итерацию цикла
breakПринудительный выход из цикла или условного оператора
TRUEЛогическое значение ИСТИНА
FALSEЛогическое значение ЛОЖЬ
NULLПустое значение
InfБесконечность
NaNНечисловое значние
NAОтсутствующее значение
NA_integer_Отсутствующее целое число
NA_real_Отсутствующее число с плавающей точкой
NA_complex_Отсутствующее комплексное число
NA_character_Отсутствующая строка

Названия переменных

Названия специальных символов

В R, как и во многих других языках программирования используются различные специальные символы. Их смысл и значение мы узнаем по ходу изучения языка, а пока что ознакомьтесь с ними, чтобы понимать как их произносить, когда они будут встречаться в программе.

СимволНазвание
$доллар
#шарп (решетка)
&амперсанд (и)
/слеш (косая черта)
\обратный слеш (обратная косая черта)
|пайп (вертикальная черта)
^циркумфлекс (крышечка)
@эт (собачка)
тильда
»одинарные кавычки
«»двойные кавычки
«обратные кавычки

Управляющие последовательности

При работе со строками вам может понадобиться знание так называемых управляющих последовательностей (escape-последовательностей). Под этим понимается совокупность подряд идущих символов, которая интерпретируется обрабатывающим механизмом как единое целое. Как правило, такие последовательности начинаются с хорошо узнаваемого символа, не являющегося буквенно-цифровым (см. предыдущий раздел)

В частности, последовательности, начинающиеся с символа обратной косой черты ( \ ) используются для управления выводом программы. Например, последовательность \n приводит к переносу строки в том месте, где она расположена, а последовательность \t позволит вставить символ табуляции. То есть, фраза «Визуализация и анализ\nгеографических данных на языке R» будет выведена в две строки с переносом после слова «анализ» :

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

Однако в данном конкретном случае проще заменить обратные слеши на прямые — Windows может работать с путями и таким образом:

В UNIX-подобных операционных системах (Linux, macOS) такой проблемы нет, поскольку для формирования пути к каталогу можно использовать только прямую косую черту ( / ). С учетом того, что Windows допускает и такой способ задания путей, в данном контексте рекомендуется всегде использовать прямые, а не обратные косые черты.

Что такое визуализация географических данных. Смотреть фото Что такое визуализация географических данных. Смотреть картинку Что такое визуализация географических данных. Картинка про Что такое визуализация географических данных. Фото Что такое визуализация географических данных

Рис. 0.5: Справка по управляющим последовательностям в R

Ссылка на пособие

Если этот курс лекций оказался полезным для вас, и вы хотите процитировать его с списке литературы вашей работы, то ссылку можно оформить по следующей форме:

Источник

Добавить комментарий

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