2015-03-06 21 views
2

Я хочу, чтобы визуализировать временные метки событий в моих данных, используя визуализацию, как показано ниже:Как визуализировать временную шкалу событий в D3?

enter image description here

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

EDIT: Основываясь на отзывах от ee2Dev, я буду делать 4 строки вместо 2, фиксируя входящие и исходящие вызовы/тексты отдельно. Что касается детализации, было бы лучше, если бы визуализация могла захватывать одну неделю данных через 5-минутные интервалы (одно текстовое сообщение будет равно 5 минутам разговора, а 48-минутный вызов будет округлен до 50-минутного вызова). Это составит 7 * 24 * 12 = 2016 возможных интервалов, что кажется несколько разумным. Возможно, 10-минутные интервалы будут более подходящими, чем 5-минутные интервалы, но я думаю, что код можно легко настроить для этого. Что-то, что я не показал, так это то, как полночь должна быть отмечена, чтобы показать, какие дни активны, а какие нет.

Ниже мой код и мой пример данные:

// Data: 
timestamp (yyyy-MM-dd HH:mm),type 
1/1/2015 10:12,inc_call 
1/2/2015 10:12,inc_call 
1/2/2015 10:12,out_text 
1/3/2015 10:12,out_call 
1/4/2015 10:12,inc_text 
1/5/2015 10:12,inc_text 


// Code 
<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

</style> 
<body> 
<script type="text/javascript" src="d3/d3.js"></script> 
<script type="text/javascript" src="papaparse.js"></script> 
<script type="text/javascript" src="jquery.js"></script> 
<script type="text/javascript" src="jquery.tipsy.js"></script> 
<link href="tipsy.css" rel="stylesheet" type="text/css" /> 
<script> 

var width = 1000; 
var height = 500; 

var events; 

var results = Papa.parse("events.csv", { 
    header: true, 
    download: true, // is needed even for local files as this interprets the input value as a path instead of simply the data 
    dynamicTyping: true, 
    delimiter: ",", 
    skipEmptyLines: true, 
    complete: function(results) { 
     events = results.data; 
     CreateVisualizationFromData(); 
     } 
}); 


var svg = d3.select("body").append("svg") 
      .attr("width", width) 
      .attr("height", height); 

var total_interactions; 

function CreateVisualizationFromData() 
{ 

    total_interactions = events.length; 
    console.log(total_interactions); 

    svg 
     .append("marker") 
     .attr("id", "arrowhead") 
     .attr("refX", 6 + 7) 
     .attr("refY", 2) 
     .attr("markerWidth", 6) 
     .attr("markerHeight", 4) 
     .attr("orient", "auto") 
     .append("path") 
     .attr("d", "M 0,0 V 4 L6,2 Z"); 


} 
+0

Прежде всего: выбор визуализации не кажется хорошим: входящие и исходящие вызовы или тексты рисуются в одной последовательности. Сначала я предлагаю вам отделить их от наличия четыре последовательности. Как алгоритм выбирает рисовать, если в один день есть много входящих и исходящих вызовов. Заполните половину области светло-голубым, а вторая половина - синим? Пропустить свет с синим? Во-вторых, не забудьте показать зрителю, какое время изображено: я не вижу, где заканчивается 1/1/2015 или где начинается 1/5/2015? Есть ли 2 - 4-е место между ними или мы показываем всего 2 дня? – ee2Dev

+0

Вы можете выбрать 4 отдельных графика, так как это действительно подходит. Альтернативный вариант также использует четыре визуализации календаря (http://bl.ocks.org/mbostock/4063318) и вместо того, чтобы заполнять весь день одним цветом, сделать ежедневный квадрат 24x24 и нарисовать 1 verticalline за каждый час, если часовая дискретизация достаточно гранулированный – ee2Dev

+0

Спасибо за комментарии. Я полностью согласен. Конечный результат должен быть 4 строки. Данные будут отображаться в течение нескольких дней, поэтому это будет 1-й-5-й. Я размышлял о том, как проиллюстрировать изменения в днях (например, с черными черными линиями при переходе на полночь), но я все еще веду себя в мозгу, чтобы понять, как он вписывается в общую визуализацию. Я обновлю исходный текст соответствующим образом. – pir

ответ

3

Чтобы дать вам использование точки, начиная этот код и идти оттуда.

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

.axis { 
    font: 10px sans-serif; 
} 

.axis path, 
.axis line { 
    fill: none; 
    stroke: #000; 
    shape-rendering: crispEdges; 
} 

.x.axis path { 
    display: none; 
} 

</style> 
<body> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script> 

var margin = {top: 20, right: 20, bottom: 30, left: 60}, 
    width = 960 - margin.left - margin.right, 
    height = 200 - margin.top - margin.bottom; 

var colorOf = d3.scale.category10(); 

var y = d3.scale.ordinal() 
    .rangeRoundBands([height, 0], 0.3); 

var x = d3.time.scale() 
    .range([5, width]); 

var yAxis = d3.svg.axis() 
    .scale(y) 
    .orient("left"); 

var xAxis = d3.svg.axis() 
    .scale(x) 
    .orient("bottom") 
    .tickFormat(d3.time.format("%m/%d/%Y %Hh"));; 

var parseDate = d3.time.format("%m/%d/%Y %H:%M").parse; 

var svg = d3.select("body").append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

d3.csv("timeseries.csv", type, function(error, data) { 
    y.domain(data.map(function(d) { return d.type; })); 
    x.domain(d3.extent(data, function(d) { return d.time; })); 
    colorOf.domain(data.map(function(d) { return d.type; })); 

    svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    svg.append("g") 
     .attr("class", "y axis") 
     .call(yAxis); 

    svg.selectAll(".bar") 
     .data(data) 
    .enter().append("rect") 
     .attr("class", "bar") 
     .attr("y", function(d) { return y(d.type); }) 
     .attr("height", y.rangeBand()) 
     .attr("x", function(d) { return x(d.time); }) 
     .attr("width", 1) 
     .style("fill", function(d) { return colorOf(d.type); }) 
}); 

function type(d) { 
    d.time = parseDate(d.time); 
    return d; 
} 

</script> 

и здесь файл timeseries.csv

time,type 
1/1/2015 10:12,inc_call 
1/2/2015 10:12,inc_call 
1/2/2015 10:12,out_text 
1/3/2015 10:12,out_call 
1/4/2015 10:12,inc_text 
1/5/2015 10:12,inc_text 

А вот JSFiddle: http://jsfiddle.net/ee2todev/6u0a0qnw/ Вы можете удалить ось у, замените его с этикетками, форматировать ось х ... отрегулируйте цвета и т. д.

+0

Спасибо, это похоже на хорошую отправную точку :) Не могли бы вы вкратце рассказать подробнее о том, что делают эти 3 строки кода? 'd3.csv (« timeseries.csv », type, function (error, data) { y.domain (data.map (function (d) {return d.type;})) x.domain (d3.extent (data, function (d) {return d.time;})) colorOf.domain (data.map (function (d) {return d.type;})); ' – pir

+0

Некоторые строки до этого, Я определяю три переменные: colorOf, x и y. Каждая из переменных указывает на функцию, в частности на функцию масштабирования. Масштабы - это функции, которые отображаются из входного домена в выходной диапазон. Диапазон каждого масштаба установлен выше - поэтому в этих трех строках я установил правильный домен. – ee2Dev

+1

Итак, первые строки задают для домена массив различных типов из ваших данных (['inc_call', 'out_text', 'out_call', 'inc_text']. Эти значения вы хотите сопоставить с разными координатами y. Вторая строка назначает минимальное и максимальное время быть областью для х. Последний отображает все типы в цвета. Обратите внимание, что y и colorOf имеют один и тот же домен (массив разных типов), но разные диапазоны (y координаты или цвета) – ee2Dev

Смежные вопросы