Как стать автором
Обновить

Как создать приложение c 3D аналитикой для iPhone?

Время на прочтение9 мин
Количество просмотров4.7K


Существует множество трендов и направлений в анализе данных, и все мы знакомы с популярными словами Business Intelligence, Big Data, Machine Learning и т.д. Эти слова знакомы сейчас даже тем, кто не знает как написать SQL-запрос, не знаком с правилами визуализации и отображения информации, и тем более не сможет написать Python-скрипт. Но всегда в нас остаётся незыблемое желание, воплощение мечты любого руководителя и/или даже аналитика данных: «нажимаешь на клавишу» и через миллисекунды нам уже приходит ответ на вопрос «Что делать?», а желательно пусть сразу «Прибыль компании увеличена».

Одной из самых основных проблем в анализе данных остается вовлечение в этот процесс человека — Человека принимающего решение. У него мало времени, или даже критически мало времени. Как вовлечь его в процесс работы большой машины анализа данных?

Ключ к быстрому пониманию данных — визуализация.

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

Но создание игры — это всегда долгий и сложный процесс.

Чтобы разрушить этот стереотип, мы придумали способ, который позволит аналитику создать «Игру с данными» для своего руководителя за пару часов.

Небольшой эксперимент


В преддверии важного события — Выборов Президента РФ 18 марта 2018 года, мы решили что было бы неплохо попробовать провернуть такой трюк именно с данными о результатах голосования.
Проанализировав информацию в интернете, мы нашли официальный источник данных о голосовании — сайт Центральной Избирательной комиссии (ЦИК РФ) izbirkom.ru. На этом сайте можно найти результаты всех проводимых выборов. Также не так давно мы наткнулись на статью на Хабре, в которой был проведен анализ данных распределения голосов по стране перед выборами депутатов Государственной думы Федерального собрания РФ, которые прошли 18 сентября 2016.

Сначала мы нашли данные результатов выборов Президента РФ за 2012 год, там же находятся и предварительные результаты голосования. Путём долгих звонков и общения со службой поддержки ЦИК нам удалось выяснить, что во время подсчёта голосов по всей стране именно эта вкладка периодически обновляется, для того, чтобы оперативно информировать избирателей о ходе выполняемой работы.

Вот так выглядит таблица с результатами выборов Президента РФ в 2012 году.



Для визуализации показателей мы использовали инструмент IDVP.Cartogram. Это сервис, который позволяет отобразить данные на интерактивной 3D Карте России. Пример приложения для iOS устройств, в котором выводятся некоторые социально-экономические показатели, доступно для скачивания в AppStore. Выглядит оно так:



Чтобы собрать такое приложение нужно пройти несколько шагов:

  • Подключение данных к IDVP;
  • Настройка отображения приложения;
  • Публикация приложения.

Далее я опишу эти шаги более подробно, но чтобы они стали понятными, погружу Вас в общую терминологию работы приложения IDVP.Cartogram.

Внутренности IDVP.Cartogram


iDVP — это платформа, которая позволяет создавать и управлять дальнейшим жизненным циклом приложений, предназначенных для визуализации данных. Визуализация может быть разной, от интерактивных отчетов в web, до десктопных или iOS-приложений с 3D графикой, именно последнее и представляет собой IDVP.Cartogram. Приложения iDVP работают по принципу веб-браузера. Любой веб-браузер содержит движок, который загружает с сервера ресурсы (html, js, css, пр.), данные и формирует графический пользовательский интерфейс с использованием стандартных визуальных элементов, таких как картинка, кнопка, текст, таблица и другие. Аналогично браузеру, в состав клиентского приложения iDVP входит движок визуализации (он называется iDVP Player) и наборы визуальных компонентов (в данном случае 3D карта и обвязка).

Вся логика приложения и конфигурация интерфейса пользователя описывается при помощи шаблонов, которые движок iDVP загружает с сервера. По аналогии с html, шаблон представляет собой xml документ (отдаленно похожий на xaml), который помимо описания интерфейса содержит логику привязки данных и обработчики событий действий пользователя. Слой визуализации клиентского приложения iDVP реализован с использованием игрового движка Unity, благодаря которому можно подключать 3D-компоненты для визуализации данных.

Приложение получает данные из модуля iDVP.Data, которое выступает одновременно как Data Integrator, ETL-инструмент и инструмент для создания web-сервисов, которые возвращают данные в JSON формате. К модулю iDVP.Data можно подключить файлы Excel и CSV, а также отдельные базы данных и REST/SOAP сервисы.

Взаимодействие отдельных компонент в приложении «Выборы 2018»:



Шаги создания приложения «Выборы 2018» в iDVP.Cartogram:


Шаг 1. Подгрузим в IDVP.Data три Excel файла, которые мы ранее получили с сайта ЦИК (на рисунке это 3 синих кружочка):

  • election_service_settings_raw — файл, где хранятся настроечные данные (такие, как названия регионов);
  • election_service_raw — подключенный сервис, с данными по предварительным результата голосования;
  • election_service_people_visit — подключенный сервис, с информацией о явке.



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




Шаг 2. Для визуализации, которая нам нужна потребуются следующие сервисы:

  • election_region_view — для вывода наименований регионов;
  • election_tables_view — для вывода данных в таблицу слева от карты;
  • election_widgets_sum — для вывода общих данных показатели по кандидатам;
  • election_widgets_all — для вывода имен кандидатов;
  • election_projects_view — для вывода списка показателей в шапке.


Для трансформации данных мы создаём сущности под названием DataSet (датасеты). Создавая цепочку таких сущностей, мы можем трансформировать исходные данные к необходимому нам формату, а также проводить аналитические вычисления при помощи SQL-скриптов.

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

Пример скрипта в основном датасете «election_information_raw»:

with elect as ( 
select
k.*,
s.region_code as region_code    
from (
 select
 	CONCAT(project, type, id) as widget_id,
 	project,
 	RTRIM(widget_name, ', %') as widget_name,
 	region_name,
 	dense_rank() over (order by region_name) as region_id,
 	max(param_1) as param_1,
 	max(param_2) as param_2
 	from (
 	  select 
 	  CASE WHEN id < 10 THEN CONCAT('0',id) ELSE CAST(id as VARCHAR) END as id,
 	  `row` as widget_name,
 	  `column` as region_name,
 	  CASE WHEN STRPOS(`row`, ', %') > 0 THEN CAST(RTRIM(`value`, '%') as FLOAT) ELSE CAST(`value` as FLOAT) END as param_1,
 	  CASE WHEN id > 18 THEN 1 ELSE 2 END as project,
 	  CASE WHEN id > 18 THEN '01' ELSE '02' END as type,
 	  CASE WHEN STRPOS(`row`, ', %') > 0 THEN CAST(RTRIM(`value`, '%') as FLOAT) ELSE CAST(null as FLOAT) END as param_2
 	  from election_service_ds_raw
 	)
 	group by
 	id,
 	type,
 	RTRIM(widget_name, ', %'),
 	project,
 	region_name
 	order by project, widget_id 
 	) k
left outer join election_service_regions_raw s on k.region_id=s.region_id   
)
 
select 
	CAST(a.region_name as VARCHAR) as region_name_table,
	CAST(a.region_code as VARCHAR) as region_code,
	CAST(a.project as VARCHAR) as project,
	CAST(a.param_1 as INTEGER) as param_1,
	CAST(a.param_2 as VARCHAR) as param_2,
	a.widget_id,
	CAST(a.widget_name as VARCHAR) as widget_name,
	CAST(s.param_1_name as VARCHAR) as param_1_name,
	CAST(s.param_2_name as VARCHAR) as param_2_name    
from elect a
left outer join election_service_widgets_raw s on CAST(SUBSTR(a.widget_id,4) as INTEGER) = CAST (s.widget_id as INTEGER)
order by project, widget_id

Результаты запроса получились следующие:



Шаг 3. Создание web-сервиса (или как мы их называем, витрины) представляет собой тоже SQL-запрос, который в секции select содержит выходные параметры, а в секции where объявленные входные параметры.



После того, как мы подключили данные, дело осталось за малым.

Шаг 4. Мы склонировали проект приложения «Cartogram», назвав его «Выборы 2018 онлайн». Далее, выгрузив локально шаблоны адаптировали их к новым витринам. Подключили визуальные компоненты к новым сервисам данных и проверили, что всё работает.

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

<Response>
    <Widget WidgetType="Widget" Name="header" BindingSide="Client">
        <Declare Name="Mode" Value="[define('Mode', '1')]" />
        <Params>
            <Param Key="Mode">
                <Bind Name="Value" Value="[Mode]"/>
            </Param>
        </Params>
 
        <DataSource Name="domains" Address="" Code="election_projects_view/execute" DisableCache="true">
            <Bind Name="Address" Value="[IdvpDataUrl]"/>
        </DataSource>
 
        <!--<Debugger Message="[Mode]"/>-->
        <StackPanelControl Orientation="Vertical">
            <StackPanelControl Orientation="Horizontal">
                <ImageControl IsColored="true" Stretch="false">
                    <Transform>
                        <Bind Name="Width" Value="[13.5 * 16 / 9 / GetWindowAspect()]"/>
                    </Transform>
                    <ImageColorARGB A="255" R="255" G="253" B="254"/>
                    <ImageControl Src="header_left" Stretch="false">
                        <Transform Depth="50" DepthAlignment="Front"/>
                    </ImageControl>
                </ImageControl>
 
                <NineRectControl Skin="default" UseColorARGB="true" Stretch="true" Width="800" Height="50" Untouchable="true">
                    <ColorARGB A="255" R="255" G="253" B="254"/>
                    <Transform>
                        <Bind Name="Width" Value="[100 - 25.5 * 16 / 9 / GetWindowAspect()]"/>
                    </Transform>
                    <StackPanelControl Orientation="Horizontal">
                        <PanelControl>
                            <Transform Width="50%"/>
                            <ButtonControl Skin="invisible" Stretch="true" Width="50" Height="50" UseColorARGB="false">
                                <Transform Height="70%" Width="90%" Margin="22% 0% 0% 0%" HorizontalAlignment="Center" />
                                <TextControl PixelSize="100" Size="11.5" Anchor="MiddleCenter" Font="FiraSansCondensed-Regular">
                                    <Transform Height="80%"/>
                                    <ColorARGB A="255" R="75" G="75" B="75"/>
                                    <Bind Name="Text" Value="[domains[1].domain_name]"/>
                                </TextControl>
                                <NineRectControl Skin="RosTur_rectangle" UseColorARGB="true" Stretch="true" Width="200" Height="10" Untouchable="true"  Condition="[Mode =='1']">
                                    <Transform Height="12%" VerticalAlignment="Bottom"/>
                                    <ColorARGB A="255" R="96" G="159" B="210"/>
                                </NineRectControl>
                                <Event Name="ModeChanged">
                                    <Params>
                                        <Param Key="Mode" Value="1"/>
                                    </Params>
                                </Event>
                            </ButtonControl>
                            <NineRectControl Skin="RosTur_header_line" UseColorARGB="false" Stretch="true" Width="1" Height="50" Untouchable="true">
                                <Transform Height="50%" Width="0.2%" HorizontalAlignment="Right" VerticalAlignment="Center"/>
                            </NineRectControl>
                        </PanelControl>
                        <PanelControl>
                            <Transform Width="50%"/>
                            <ButtonControl Skin="invisible" Stretch="true" Width="50" Height="50" UseColorARGB="false">
                                <Transform Height="70%" Width="90%" Margin="22% 0% 0% 0%" HorizontalAlignment="Center" />
 
                                <TextControl PixelSize="100" Size="11.5" Anchor="MiddleCenter" Font="FiraSansCondensed-Regular">
                                    <Transform Height="80%"/>
                                    <ColorARGB A="255" R="75" G="75" B="75"/>
                                    <Bind Name="Text" Value="[domains[2].domain_name]"/>
                                </TextControl>
                                <NineRectControl Skin="RosTur_rectangle" UseColorARGB="true" Stretch="true" Width="200" Height="10" Untouchable="true" Condition="[Mode =='2']">
                                    <Transform Height="12%" VerticalAlignment="Bottom"/>
                                    <ColorARGB A="255" R="96" G="159" B="210"/>
                                </NineRectControl>
                                <Event Name="ModeChanged">
                                    <Params>
                                        <Param Key="Mode" Value="2"/>
                                    </Params>
                                </Event>
                            </ButtonControl>
                        </PanelControl>
                    </StackPanelControl>
                </NineRectControl>
                <ImageControl IsColored="true" Stretch="true">
                    <Transform>
                        <Bind Name="Width" Value="[12 * 16 / 9 / GetWindowAspect()]"/>
                    </Transform>
                    <ImageColorARGB A="255" R="255" G="253" B="254"/>
                    <ImageControl Src="header_right" Stretch="false">
                        <Transform Depth="50" DepthAlignment="Front"/>
                    </ImageControl>
                    <EmptyButtonControl>
                        <Event Name="OpenUrl">
                            <Params>
                                <Param Key="Url" Value="http://idvp.info"/>
                            </Params>
                        </Event>
                    </EmptyButtonControl>
                </ImageControl>
            </StackPanelControl>
        </StackPanelControl>
    </Widget>
</Response>

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




У нас всё получилось


Во время публикации предварительных, а далее и финальных результатов выборов Президента РФ 2018, мы автоматически публикуем данные в общедоступном приложении «Выборы 2018», как только они появляются на сайте ЦИК. Если Вам будет интересно, обязательно скачивайте приложение в AppStore и GooglePlay. Следите за происходящим вместе с нами.
Аналитики а также разработчики в ближайшем будущем смогут получить бесплатный-демо доступ к платформе IDVP для того чтобы научиться создавать такие же приложения и многое другое. Сообщите о себе на сайте IDVP или напишите в Телеграм.

Если нам удастся вовлечь Вас в процесс наблюдения за результатами выборов, то и Вам удастся в дальнейшем вовлекать в процесс анализа данных Вашего босса. Но мы уверены, что у Вас может получиться лучше. Данные Выборов Президента это всего лишь один из поводов, возможно уже на следующей неделе мы в нашем приложении будем мониторить не только результаты выборов, но и статистику использования IDVP.Cartogram по всей стране ;)

Анализ данных — это не просто автоматический процесс получения ответа на вопрос, это процесс взаимодействия людей и данных. Только простые и понятные инструменты свяжут всё воедино.
Теги:
Хабы:
+4
Комментарии2

Публикации

Изменить настройки темы

Истории

Работа

Data Scientist
62 вакансии

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн