Недорогая бизнес-аналитика с Apache Hadoop и Dojo: Часть 2. Cоздание привлекательных интерактивных отчетов с использованием Dojo Toolkit

Воспользуйтесь преимуществами диаграмм Dojo Сharts

Всегда очень важно понимать, чем занимается ваша компания. Она может быть сколь угодно гибкой, но, не зная следующего верного шага, вы движетесь с закрытыми глазами. Системы бизнес-аналитики могут быть чрезвычайно дорогими и часто требуют для своей работы изменения ваших данных. Однако современные технологии с открытыми исходными кодами как никогда облегчают составление настроенных под ваши нужды аналитических отчетов. В этой статье, второй в серии из двух частей, рассказывается, как собрать аналитические данные, созданные Apache Hadoop, и использовать их для создания радующих глаз интерактивных отчетов при помощи Dojo Toolkit.

Майкл Галпин, инженер по программному обеспечению, Vitria Technology

Майкл Галпин (Michael Galpin) имеет учёную степень по математике в Калифорнийском Технологическом институте. Он является Java-разработчиком с конца 90-х гг. и работает инженером по программному обеспечению в Vitria Technology, в Саннивейл, Калифорния.



29.02.2011

Предварительные требования

В данной статье мы будем использовать данные, созданные Apache Hadoop в первой части данной серии статей. Основное внимание уделяется использованию инфраструктуры Dojo Toolkit (в данной статье применяется версия 1.4). В нашем примере для загрузки Dojo на страницу мы будем использовать Ajax API Google (см. раздел Ресурсы), поэтому загрузка Dojo не требуется. Что касается опыта, необходимо знать только JavaScript. Ссылки на эти инструменты приведены в разделе Ресурсы.

Графические отчеты при помощи Dojo

В первой части (EN) данной серии мы увидели, как можно сократить большой объем данных при помощи Apache Hadoop. В приведенном примере мы использовали Hadoop для обработки журналов доступа к серверу Apache. С помощью Hadoop мы преобразовали эти журналы в аналитические данные, которые содержат информацию о Web-браузерах, используемых пользователями вашего Web-сайта. Одним из полезных действий, выполненных при помощи Hadoop, было преобразование этих данных в JSON-формат, поскольку мы в конечном итоге собираемся написать Web-приложение, которое будет потреблять эти данные и формировать графический отчет. В листинге 1 показан пример данных, используемый в данной статье.

Листинг 1. Пример данных с информацией об используемых браузерах
[
    {"month" : "January 2010", "data": 
        {"IE8":5339680,"IPHONE":176397,"SAFARI":1161063,
        "FF35":5334121,"OTHER":1697189,"IE6":2355910,"OPERA":293024,
        "IE7":3448568,"FF3":1425939,"CHROME":1381381}},
    {"month" : "February 2010", "data": 
        {"IE8":4420267,"IPHONE":122378,"SAFARI":937765,
        "FF35":4904831,"OTHER":1249727,"IE6":1824138,"OPERA":261245,
        "IE7":2548741,"FF3":848517,"CHROME":1122684}},
    {"month" : "March 2010", "data" : 
        {"IE8":4832154,"IPHONE":124723,"SAFARI":1004835,
        "FF35":5240639,"OTHER":1443493,"IE6":1782140,"OPERA":288338,
        "IE7":2705560,"FF3":728227,"CHROME":1250771}},
    {"month" : "April 2010", "data" : 
        {"IE8":6014148,"IPHONE":153317,"SAFARI":1184909,
        "FF35":6355369,"IE6":2023596,"OTHER":1701331,"OPERA":336320,
        "IE7":3083772,"FF3":794613,"CHROME":1895022}},
    {"month" :"May 2010", "data" : 
        {"IE8":3985522,"IPHONE":107109,"SAFARI":826693,
        "FF35":4443157,"OTHER":1350928,"IE6":1169420,"OPERA":230201,
        "IE7":2032111,"FF3":471397,"CHROME":1358771}},
    {"month" :"June 2010", "data" : 
        {"IE8":4944664,"IPHONE":143594,"SAFARI":597916,
        "FF35":5396690,"OTHER":1740354,"IE6":1367462,"OPERA":264916,
        "IE7":2318786,"FF3":511660,"CHROME":1594828}}
]

Это данные, которые генерирует Hadoop-задание, разработанное в первой части серии статей. В нашем примере мы напрямую включим эти данные в Web-страницу, но можно было бы легко записать их в отдельный файл и загружать его при помощи Ajax. Как показано в листинге 1, мы имеем статистику по браузерам за шесть месяцев, представленную в формате JSON. Эти данные можно очень легко использовать в Web-приложении при создании отчета.

Как на стороне сервера, так и на стороне клиента есть множество инфраструктур и библиотек, которые можно использовать для создания отчетов на основании этих данных. Для создания интерактивного отчета нужно решение на стороне клиента, и Dojo Toolkit идеально подходит для этого. Он имеет в своем составе двумерные и трехмерные диаграммы. Мы остановимся на двумерных диаграммах. В листинге 2 показано, как создать простую диаграмму.

Листинг 2. Создание простой секторной диаграммы при помощи Dojo
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hadoop Reports</title>
<script type="text/javascript"
    src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js"
    djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
    dojo.require("dojox.charting.Chart2D");
    var pieChart = {};
      var stats; // see Listing 1 for the stats
    function init(){
        pieChart = new dojox.charting.Chart2D("pie-chart");
        pieChart.addPlot("default", {
            type: "Pie",
            radius: 300,
            fontColor: "black",
            labelOffset : "-50"
        });
        var lastMonth = stats[stats.length -1];
        pieChart.addSeries("browsers", makePieSeries(lastMonth.data));
        pieChart.render();
    }
    function makePieSeries(data){
        var series = [];
        var total = 0;
        var key = ";
        for (key in data){
            total += data[key];
        }
        var label = ";
        for (key in data){
            label = key;
            label += " : ";
            label += data[key] * 100.0 / total;
            label += "%";
            series.push({y:data[key], text:label});
        }
        return series;            
    }
    dojo.addOnLoad(init);
</script>
</head>
<body>
<div id="pie-chart" style="width: 800px; height: 750px;"></div>
</body>
</html>

Прежде всего обратите внимание на блок script. Для загрузки объекта 2D-диаграммы Dojo dojox.charting.Chart2D используется система управления пакетами (dojo.require). В последней строке блока script функция dojo.addOnLoad активизирует функцию init при завершении загрузки Web-страницы. В функции init создается секторная диаграмма, и в конструктор передается строка pie-chart. Это указывает Dojo найти HTML-элемент с ID pie-chart и использовать его как родительский элемент создаваемого графика. Данный элемент можно увидеть в HTML-структуре в листинге 2.

После возврата в функцию init выполняется вызов метода addPlot созданного объекта chart. Здесь указываются параметры диаграммы, включая ее тип. Dojo поддерживает много типов диаграмм. В данном случае указывается тип Pie. Для каждого конкретного типа диаграммы имеется множество специфичных параметров. В нашем случае, например, указывается радиус секторной диаграммы – параметр, которого нет в диаграммах другого типа.

Затем вызывается метод addSeries объекта chart. Здесь передаются данные из листинга 1. Однако нужно немного изменить эти данные, чтобы они нормально работали с секторной диаграммой Dojo; этим занимается функция makePieSeries. Она принимает данные браузера и возвращает массив простых объектов. Каждый объект имеет два свойства: y и text. Объект y – это значение, а text – метка. Большая часть кода функции makePieSeries занимается созданием метки, которая будет отображать название браузера, количество посещений и процент от общего числа посещений.

После возврата в функцию init выполняется последний вызов функции render. Именно эта функция указывает Dojo нарисовать диаграмму на Web-странице. Как упоминалось ранее, некоторые параметры диаграммы и ряда отличаются в зависимости от типа диаграммы. Однако шаблон addPlot/addSeries/render является общим. На рисунке 1 показан пример готовой диаграммы.

Рисунок 1. Простая секторная диаграмма, отображающая статистику по браузерам за июнь
Рисунок 1. Простая секторная диаграмма, отображающая статистику по браузерам за июнь

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


Добавление привлекательности

Dojo позволяет легко создавать простые секторные диаграммы, подобные той, которая показана на рисунке 1. Возможно, это не совсем то, что вы хотели бы показать руководству. К счастью, Dojo позволяет легко добавлять некоторые украшательства. В листинге 3 показано обновление кода листинга 2, которое позволит создать полноцветную интерактивную секторную диаграмму.

Листинг 3. Код цветной секторной диаграммы
dojo.require("dojox.charting.Chart2D");
dojo.require("dojox.charting.themes.Shrooms");
dojo.require("dojox.charting.action2d.MoveSlice");
dojo.require("dojox.charting.action2d.Tooltip");

function init(){
    pieChart = new dojox.charting.Chart2D("pie-chart");
    pieChart.addPlot("default", {
        type: "Pie",
        radius: 300,
        fontColor: "black",
        labelOffset : "-50"
    });
    var lastMonth = stats[stats.length -1];
    pieChart.addSeries("browsers", makePieSeries(lastMonth.data));
    var slice = 
          new dojox.charting.action2d.MoveSlice(pieChart,"default");
    var tip = new dojox.charting.action2d.Tooltip(pieChart,"default",{
        text : function(o) { 
            var run = o.run;
            var item = run.data[o.index];
            var label = item.text;
            var split = label.split(" : ");
            var browser = split[0];
            var percentage = split[1];
            var total = item.y;
            return browser + " : " + total + " (" + percentage + ")"; 
        }
    });
    pieChart.setTheme(dojox.charting.themes.Shrooms);
    pieChart.render();
}

Первое, что бросается в глаза в листинге 3, – добавление нескольких новых вызовов dojo.require. Далее в коде вы увидите ссылку на каждый из этих объектов. Первый из них – объект MoveSlice. Это простая анимация, которая увеличивает сектор при наведении на него курсора мыши. Затем используется объект Tooltip. Он дает возможность задать подсказку – некий дополнительный текст, который появляется при наведении курсора на сектор. По умолчанию отображается просто текстовая метка конкретного сектора диаграммы. Если нужно показать что-нибудь другое, как это сделано здесь, используйте функцию text. Эта функция генерирует текст, отображающийся в виде подсказки. В данном случае будет отображаться примерно следующее: FF35 : 5334121 (27.48%). Наконец, последней добавленной строкой является вызов метода setTheme вашей диаграммы, в которой передается одна из многих цветовых тем, предоставляемых Dojo. В данной цветовой схеме используется несколько ярких цветов. На рисунке 2 показана полноцветная версия секторной диаграммы.

Рисунок 2. Яркая изящная секторная диаграмма
Рисунок 2. Яркая изящная секторная диаграмма

Теперь она стала намного лучше. Как видно из листинга 3, данная тема называется Shrooms - возможно, вы догадываетесь, почему. Если она кажется излишне яркой, можно выбрать одну из более чем 30 тем, предоставляемых Dojo. Также можно довольно легко создать свою собственную тему. Более того, можно вообще не использовать темы, а напрямую указать цвет каждого сектора диаграммы. Диаграммы, представленные на рисунках 1 и 2, отображают данные из листинга 1 только за июнь. Давайте рассмотрим, как можно представить данные за другие месяцы.


Работа с несколькими рядами

Можно взять код листинга 3 и использовать его для визуализации диаграмм для каждого месяца на основании данных листинга 1. Каждый раз нужно было бы создавать новую секторную диаграмму, что не очень эффективно. Имеется более элегантный и эффективный способ изменения данных, используемых диаграммой. В листинге 4 представлена модифицированная версия секторной диаграммы, позволяющая пользователю выбирать, какие ряды отображать.

Листинг 4. Секторная диаграмма с элементами управления для переключения данных
function init(){
    // аналогично листингу 3
    var chooser = dojo.byId("series-selector");
    var i = 0;
    var monthlyStats = null;
    var opt = null;
    for (i=0;i<stats.length;i++){
        monthlyStats = stats[i];
        opt = dojo.doc.createElement("option");
        opt.value = i;
        opt.appendChild(dojo.doc.createTextNode(monthlyStats.month));
        chooser.appendChild(opt);
    }
}
function aggregateResults(results){
    var aggResults = {};
    aggResults["IE"] = results.IE8 + results.IE7 + results.IE6;
    aggResults["FF"] = results.FF35 + results.FF3;
    aggResults["SAFARI"] = results.SAFARI + results.IPHONE;
    aggResults["CHROME"] = results.CHROME;
    aggResults["OPERA"] = results.OPERA;
    aggResults["OTHER"] = results.OTHER;
    return aggResults;
}
function selectSeries(){
    var selected = dojo.byId("series-selector").value;
    var aggBox = dojo.byId("aggBox").value;
    var series = stats[selected].data;
    if (aggBox){
        series = aggregateResults(series);
    }
    pieChart.updateSeries("browsers", makePieSeries(series));
    pieChart.render();
}
...
<div id="commandBar">
    <label for="series-selector">Choose Data:</label>
    <select name="series-selector" id="series-selector" 
           onchange="selectSeries()">
    </select>
    <label for="aggBox">Aggregate Data?</label>
    <input type="checkbox" id="aggBox" name="aggBox" 
          onchange="selectSeries()"/>
</div>

Код, представленный в листинге 4, добавляет в диаграмму несколько элементов управления. Во-первых, это ниспадающий список, отображающий все ряды данных из листинга 1. Эти данные динамически загружаются в функцию init. Есть также флажок, позволяющий пользователю указать, нужно ли агрегировать данные, т.е. нужно ли суммировать все версии Internet Explorer.

При изменении любого из этих элементов управления вызывается функция selectSeries. Эта функция берет значения из HTML-элементов управления для определения тех рядов данных, которые следует использовать. Затем она проверяет, отмечен ли флажок агрегирования, и, если это так, применяет функцию aggregateResults к выбранным рядам. Наконец, она обновляет диаграмму, активизируя метод updateSeries и повторно вызывая render. На рисунке 3 представлена секторная диаграмма с новыми элементами управления.

Рисунок 3. Интерактивная секторная диаграмма
Рисунок 3. Интерактивная секторная диаграмма

Теперь можно переключать ряды данных и даже выполнять их агрегирование перед созданием секторной диаграммы. Все темы и эффекты тоже применимы, поскольку это та же самая диаграмма. Вы просто переключаете данные, используемые диаграммой. Это диаграмма полезна для определения наиболее применяемой версии браузера в любой момент времени. Однако секторная диаграмма не подходит, если вы хотите увидеть тренды (например, какие браузеры становятся более популярны, а какие менее). Давайте рассмотрим другой тип диаграмм Dojo, который можно использовать для отображения трендов.


Анализ трендов с несколькими рядами

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

Листинг 5. Код преобразования данных для трендового анализа
var xStats = {};
function calcStats(){
    var i = 0;
    var mStats = null;
    var browser = ";
    var total = 0;
    for (i=0;i<stats.length;i++){
        mStats = (stats[i]).data;
        total = 0;
        for (browser in mStats){
            total += mStats[browser];
        }
        for (browser in mStats){
            if (!xStats[browser]){
                xStats[browser] = [];
            }
            xStats[browser].push(mStats[browser] / total);
        }
    }
}
dojo.addOnLoad(calcStats);

В листинге 5 сначала создается глобальная переменная xStats для хранения новых данных. Затем определяется функция calcStats, выполняющая необходимое преобразование. Эта функция выполняет итерирование по каждому месяцу. Сначала она суммирует общее число посещений с использованием определенного браузера за месяц. Затем при повторном итерировании по каждому браузеру вычисляется доля браузера за данный месяц и добавляется к xStats. В итоге xStats становится отображением, ключами которого являются браузеры, а значениями – массивы со значениями доли использования определенного браузера с января по июнь. Это именно те хронологические данные, которые необходимы нам для отображения трендов. Наконец, выполняется еще один вызов dojo.addOnLoad, чтобы эта функция выполнялась при запуске. Теперь ее нужно просто включить в диаграмму. В листинге 6 показано, как можно создать линейную диаграмму, отображающую эти данные.

Листинг 6. Создание линейной диаграммы данных анализа тренда
dojo.require("dojox.charting.widget.Legend");
function makeTrends(){
    var chart = new dojox.charting.Chart2D("trends");
    chart.addPlot("default", {
        type: "Lines",
        markers : true,
        tension : "S",
        lines : true,
        labelOffset : -30,
        shadows : {dx:2, dy:2, dw:2}
    });
    chart.addAxis("x");
    chart.addAxis("y", {vertical:true});
    var browser = ";
    for (browser in xStats){
        chart.addSeries(browser, makeSeries(xStats[browser]));
    }
    chart.setTheme(dojox.charting.themes.Shrooms);
    chart.render();
    var legend =  new dojox.charting.widget.Legend({chart: chart}, 
          "legend");
}    
function makeSeries(data){
    var series = [];
    var i = 1;
    for (var key in data){
        series.push({x: i++, y :data[key]});
    }
    return series;        
}
dojo.addOnLoad(makeTrends);
<div id="trends" style="width: 800px; height: 800px;"></div>
<div id="legend"></div>

Снова наш код начинается с добавления новой Dojo-зависимости. На этот раз это объект dojox.charting.widget.Legend (более подробно о нем далее). Затем указывается функция makeTrends, которая создаст новую диаграмму. Этот код аналогичен коду для создания секторной диаграммы. На этот раз у нас есть несколько типов линий (Lines). Имеется несколько параметров, специфичных для линейных диаграмм, например, маркеры (markers), отображающие точки данных, натяжение (tension), изгибающее линии, и тени (shadows), отображающие тень каждой линии. Отметим, что мы также добавили две оси, креативно названные x и y. Затем добавляются ряды для каждого браузера, сохраненного в объекте xStats. Для каждого браузера выполняется вызов функции makeSeries. Она, по существу, преобразует данные в пары (x,y), где x – это месяц (1=январь, 2=февраль и т.д.), а y – доля браузера в процентах за данный месяц. После возврата в makeTrends выполняется вызов метода setTheme, опять работающего с Shrooms, а затем вызывается render. Наконец, при помощи упоминавшегося ранее объекта Legend создается блок условных обозначений (легенда). На рисунке 4 показан результат.

Рисунок 4. Диаграмма трендов данных
Рисунок 4. Диаграмма трендов данных

На этой диаграмме можно видеть тенденцию к росту со временем применения браузеров Firefox® 3.5 и Internet Explorer® 8, тогда как доля более старых версий данных браузеров уменьшается. Существует много других типов диаграмм, с которыми можно поэкспериментировать, используя данный код. Например, интересен тип StackedLines. Также можно комбинировать некоторые методики, описанные ранее, например, изменение рядов данных (допустим, для добавления агрегирования).


Заключение

В данной статье рассматривались основы создания интерактивных диаграмм при помощи Dojo Toolkit. Вы познакомились только с двумя типами диаграмм, поддерживаемых Dojo. Многие типы имеют уникальные возможности, которые можно использовать для создания по-настоящему привлекательных отчетов. Прочтите документацию по Dojo и познакомьтесь с вариантами, которые можно использовать для создания впечатляющих диаграмм в приложениях отчетов.


Загрузка

ОписаниеИмяРазмер
Исходный код статьиreports.zip3 КБ

Ресурсы

Научиться

Получить продукты и технологии

  • Загрузите Apache Hadoop. В данной статье использовалась версия 0.20.
  • Загрузите Java SDK. В данной статье использовался JDK 1.6.0_17.
  • Google Libraries API: используйте интерфейсы Google Ajax API для загрузки Dojo на вашу страницу.
  • Познакомьтесь с инфраструктурами Pig и Hive, разработанными на основе Hadoop.

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


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

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



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

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Web-архитектура, SOA и web-сервисы
ArticleID=799272
ArticleTitle=Недорогая бизнес-аналитика с Apache Hadoop и Dojo: Часть 2. Cоздание привлекательных интерактивных отчетов с использованием Dojo Toolkit
publish-date=02292011