Статьи

Приложение для визуализации данных с использованием GAE Python, D3.js и Google BigQuery: часть 2

В первой части этой серии мы создали приложение Python и развернули его в Google App Engine (GAE). Из приложения мы подключили его к набору данных Google BigQuery и загрузили данные в наше приложение. В этом руководстве мы увидим, как визуализировать данные с помощью библиотеки JavaScript D3.js.

D3.js — это библиотека JavaScript для создания документов, управляемых данными. Он использует возможности HTML5, SVG и CSS3 для создания интерактивных визуализаций на основе произвольных данных. Он также использует различные преобразования, чтобы сделать отображение визуально более привлекательным.

С официального сайта D3.js :

D3.js — это библиотека JavaScript для управления документами на основе данных. D3 поможет вам оживить данные, используя HTML, SVG и CSS. Акцент D3 на веб-стандартах дает вам все возможности современных браузеров, не привязывая себя к проприетарной структуре, сочетая мощные компоненты визуализации и управляемый данными подход к манипулированию DOM.

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

1
<script src=»http://d3js.org/d3.v3.min.js» charset=»utf-8″></script>

Теперь все готово для создания нашего графа с использованием D3.js.

Во-первых, клонируйте исходный учебный код из GitHub .

1
git clone https://github.com/jay3dec/PythonD3jsMashup_Part1.git

Мы создадим новую страницу для отображения нашего графика. Давайте displayChart.html это displayChart.html . Поэтому перейдите к PythonD3jsMashup_Part1/Templates/ и создайте новую страницу с именем displayChart.html . Добавьте следующий HTML-код к нему:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang=»en»>
 
<head>
    <meta http-equiv=»Content-Type» content=»text/html; charset=UTF-8″>
 
    <link rel=»icon» href=»http://getbootstrap.com/favicon.ico»>
 
    <link href=»http://getbootstrap.com/dist/css/bootstrap.min.css» rel=»stylesheet»>
 
    <link href=»http://getbootstrap.com/examples/justified-nav/justified-nav.css» rel=»stylesheet»>
     
     <script type=»text/javascript» src=»js/d3.js»></script>
 
 
</head>
 
<body>
 
    <div class=»container»>
 
        <div class=»jumbotron»>
            <h1>Chart Will be Here!!</h1>
        </div>
 
 
        <div class=»footer»>
            <p>© Company 2014</p>
        </div>
 
    </div>
 
</body>
 
</html>

Перейдите в каталог PythonD3jsMashup_Part1 и откройте app.py Теперь нам нужно включить маршрут для вновь добавленной страницы displayChart.html . Ниже приведена часть app.py где для приложения объявлены существующие маршруты.

1
2
3
4
application = webapp2.WSGIApplication([
    (‘/chart’,ShowChartPage),
    (‘/’, ShowHome),
], debug=True)

Точно так же мы добавим еще один маршрут /displayChart и установим его в класс DisplayChart который мы объявим следующим. Вот недавно добавленный маршрут:

1
2
3
4
5
application = webapp2.WSGIApplication([
    (‘/chart’,ShowChartPage),
    (‘/displayChart’,DisplayChart),
    (‘/’, ShowHome),
], debug=True)

Теперь давайте создадим обработчик класса для /displayChart для отображения страницы шаблона. Мы будем использовать функцию template.render для отображения страницы шаблона. Вот недавно добавленный обработчик класса для отображения displayChart.html .

1
2
3
4
5
class DisplayChart(webapp2.RequestHandler):
   def get(self):
       template_data = {}
       template_path = ‘Templates/displayChart.html’
       self.response.out.write(template.render(template_path,template_data))

Сохраните все и перезапустите сервер.

1
dev_appserver.py PythonD3jsMashup_Part1/

Укажите в браузере http: // localhost: 8080 / displayChart, и вы должны увидеть недавно добавленный шаблон страницы.

Недавно добавленный шаблон страницы

Масштабируемая векторная графика (SVG) — это формат изображения на основе XML для рисования 2D-графики с поддержкой интерактивности и анимации. Мы будем использовать элемент SVG, на котором мы будем рисовать наш график. Итак, давайте сначала создадим элемент SVG.

1
2
3
4
5
6
7
<div id=»D3line» class=»jumbotron»>
 
    <h1>Chart Will be Here!!</h1>
     
    <svg id=»visualisation» width=»1000″ height=»500″></svg>
 
</div>

Теперь давайте создадим JavaScript-функцию InitChart для инициализации диаграммы. Включите сценарий в конце страницы.

Прежде чем начать, давайте предположим, что определенный набор данных, как показано. Позже мы заменим данные примера данными из набора данных Google BigQuery.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
var data = [{
    «count»: «202»,
    «year»: «1590»
}, {
    «count»: «215»,
    «year»: «1592»
}, {
    «count»: «179»,
    «year»: «1593»
}, {
    «count»: «199»,
    «year»: «1594»
}, {
    «count»: «134»,
    «year»: «1595»
}, {
    «count»: «176»,
    «year»: «1596»
}, {
    «count»: «172»,
    «year»: «1597»
}, {
    «count»: «161»,
    «year»: «1598»
}, {
    «count»: «199»,
    «year»: «1599»
}, {
    «count»: «181»,
    «year»: «1600»
}, {
    «count»: «157»,
    «year»: «1602»
}, {
    «count»: «179»,
    «year»: «1603»
}, {
    «count»: «150»,
    «year»: «1606»
}, {
    «count»: «187»,
    «year»: «1607»
}, {
    «count»: «133»,
    «year»: «1608»
}, {
    «count»: «190»,
    «year»: «1609»
}, {
    «count»: «175»,
    «year»: «1610»
}, {
    «count»: «91»,
    «year»: «1611»
}, {
    «count»: «150»,
    «year»: «1612»
}];

Сначала мы определим несколько констант, связанных с графиком, таких как его ширина, высота и поля слева, справа, сверху и снизу, которые мы будем использовать при создании графика. Итак, давайте выберем элемент SVG с помощью d3.select и определим наши константы.

1
2
3
4
5
6
7
8
9
var vis = d3.select(«#visualisation»),
   WIDTH = 1000,
   HEIGHT = 500,
   MARGINS = {
       top: 20,
       right: 20,
       bottom: 20,
       left: 50
   };

Чтобы отобразить наши данные, нам нужно определить шкалы по X axis Y axis таким образом, чтобы при динамическом поступлении данных шкалы корректировались соответствующим образом. D3.js предоставляет несколько API-интерфейсов для упрощения работы. Одним из таких API является d3.scale.linear , который мы будем использовать для создания нашего масштаба на основе максимальных и минимальных значений данных.

При этом у нас есть два новых термина, которые называются Range и Domain . Range представляет область, которую мы должны отобразить для визуализации, а Domain представляет максимальное и минимальное значения данных, которые мы будем визуализировать в области svg .

Теперь мы создадим наши масштабы, используя d3.scale.linear и определим диапазон и домен для созданных масштабов.

1
xScale = d3.scale.linear().range(MARGINS.left, WIDTH — MARGINS.right).domain([1590,1612]);

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

Аналогично, мы также определим масштаб для оси Y.

1
yScale = d3.scale.linear().range(HEIGHT — MARGINS.top, MARGINS.bottom).domain([91,215]);

Поскольку весы готовы, мы будем двигаться к созданию осей. Для этого D3.js предоставляет API под названием d3.svg.axis . Итак, мы будем использовать API для создания осей и установки для них созданных выше масштабов.

1
2
3
4
5
xAxis = d3.svg.axis()
    .scale(xScale),
 
yAxis = d3.svg.axis()
    .scale(yScale);

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

1
vis.append(«svg:g»)

Теперь мы установим созданный выше xAxis в контейнер svg как показано ниже:

1
2
vis.append(«svg:g»)
   .call(xAxis);

Точно так же для yAxis :

1
2
vis.append(«svg:g»)
   .call(yAxis);

Вот функция InitChart которую мы только что создали.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
function InitChart() {
    var data = [{
        «count»: «202»,
        «year»: «1590»
    }, {
        «count»: «215»,
        «year»: «1592»
    }, {
        «count»: «179»,
        «year»: «1593»
    }, {
        «count»: «199»,
        «year»: «1594»
    }, {
        «count»: «134»,
        «year»: «1595»
    }, {
        «count»: «176»,
        «year»: «1596»
    }, {
        «count»: «172»,
        «year»: «1597»
    }, {
        «count»: «161»,
        «year»: «1598»
    }, {
        «count»: «199»,
        «year»: «1599»
    }, {
        «count»: «181»,
        «year»: «1600»
    }, {
        «count»: «157»,
        «year»: «1602»
    }, {
        «count»: «179»,
        «year»: «1603»
    }, {
        «count»: «150»,
        «year»: «1606»
    }, {
        «count»: «187»,
        «year»: «1607»
    }, {
        «count»: «133»,
        «year»: «1608»
    }, {
        «count»: «190»,
        «year»: «1609»
    }, {
        «count»: «175»,
        «year»: «1610»
    }, {
        «count»: «91»,
        «year»: «1611»
    }, {
        «count»: «150»,
        «year»: «1612»
    }];
 
 
 
    var vis = d3.select(«#visualisation»),
        WIDTH = 1000,
        HEIGHT = 500,
        MARGINS = {
            top: 20,
            right: 20,
            bottom: 20,
            left: 50
        },
         
        xScale = d3.scale.linear().range([MARGINS.left, WIDTH — MARGINS.right]).domain([1590, 1612]),
         
        yScale = d3.scale.linear().range([HEIGHT — MARGINS.top, MARGINS.bottom]).domain([91, 215]),
         
        xAxis = d3.svg.axis()
        .scale(xScale),
 
        yAxis = d3.svg.axis()
        .scale(yScale);
 
 
 
 
    vis.append(«svg:g»)
        .call(xAxis);
 
    vis.append(«svg:g»)
        .call(yAxis);
}

Сохраните все изменения и вызовите функцию при загрузке страницы. Перезапустите сервер и укажите в браузере http: // localhost: 8080 / displayChart , и вы должны увидеть экран ниже.

Диаграмма с некоторыми добавленными данными

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

Чтобы разделить обе перекрывающиеся оси, нам нужно переместить X axis вниз. Мы будем использовать свойство transform для перемещения X axis вниз. Существуют различные типы преобразований, которые доступны. Мы будем использовать конкретное преобразование translate чтобы переместить его вниз. Используя translate transform, мы можем перемещать оси на основе координат. При использовании translate нам нужно указать координаты X и Y, на которые необходимо переместить ось. Поскольку мы хотим, чтобы ось X двигалась вниз, мы указываем только координату Y и оставляем координату X на 0. Вот как это выглядит после добавления атрибута transform.

1
2
3
vis.append(«svg:g»)
   .attr(«transform», «translate(0,» + (HEIGHT — MARGINS.bottom) + «)»)
   .call(xAxis);

Сохраните изменения и перезапустите сервер. Укажите в браузере http: // localhost: 8080 / displayChart, и вы должны увидеть экран ниже.

Диаграмма с созданной осью X

Далее нам нужно изменить ориентацию оси Y. Мы можем указать ориентацию оси, используя ориентацию . Поэтому измените yAxis как показано ниже, чтобы изменить ее ориентацию.

1
2
3
yAxis = d3.svg.axis()
   .scale(yScale)
   .orient(«left»);

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

1
2
3
vis.append(«svg:g»)
   .attr(«transform», «translate(» + (MARGINS.left) + «,0)»)
   .call(yAxis);

Как видно из приведенного выше кода, мы просто переместили ось Y вдоль координаты X (20 слева), чтобы вывести ее на изображение. Сохраните изменения и обновите страницу, и вы увидите экран ниже.

Добавлена ​​диаграмма с обеими осями

Итак, у нас есть оси X и Y, хотя они выглядят немного некрасиво. Давайте применим некоторые стили и сделаем так, чтобы они выглядели хорошо. Включите следующие стили CSS:

01
02
03
04
05
06
07
08
09
10
.axis path {
fill:none;
stroke:#777;
shape-rendering:crispEdges;
}
 
.axis text {
font-family:Lato;
font-size:13px;
}

Добавьте следующие стили CSS к осям, используя свойство атрибута CSS.

1
2
3
4
5
6
7
8
9
vis.append(«svg:g»)
    .attr(«class», «x axis»)
    .attr(«transform», «translate(0,» + (HEIGHT — MARGINS.bottom) + «)»)
    .call(xAxis);
 
vis.append(«svg:g»)
    .attr(«class», «y axis»)
    .attr(«transform», «translate(» + (MARGINS.left) + «,0)»)
    .call(yAxis);

Обновите страницу, и вы должны увидеть экран ниже:

Диаграмма с добавленными стилями CSS

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

D3.js предоставляет функции с d3.min и d3.max для получения минимальных и максимальных значений из массива. Мы можем использовать эти функции, чтобы получить максимальные и минимальные значения для нашего домена на основе образца набора данных. Предположим, у нас есть массив данных. Используя d3.min мы можем получить минимальное значение.

1
2
3
d3.min(data, function(d) {
    return d.value;
})

Аналогично, чтобы получить максимальное значение:

1
2
3
d3.max(data, function(d) {
    return d.value;
})

Теперь мы yScale xScale и yScale чтобы сделать значения домена динамическими.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
xScale = d3.scale.linear().range([MARGINS.left, WIDTH — MARGINS.right]).domain([d3.min(data, function(d) {
        return (parseInt(d.year) — 5);
    }),
    d3.max(data, function(d) {
        return parseInt(d.year, 10);
    })
]);
 
 
yScale = d3.scale.linear().range([HEIGHT — MARGINS.top, MARGINS.bottom]).domain([d3.min(data, function(d) {
        return (parseInt(d.count) — 5);
    }),
    d3.max(data, function(d) {
        return parseInt(d.count, 10);
    })
]);

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

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

Код из этого урока доступен на GitHub .