Bagaimana cara memvisualisasikan timeline acara di D3?

Saya ingin memvisualisasikan stempel waktu peristiwa di data saya menggunakan visualisasi seperti yang ditunjukkan di bawah ini:

masukkan deskripsi gambar di sini

Saya kira ini dapat dilakukan dengan beberapa cara berbeda dan dengan kurangnya pengalaman saya dengan D3, saya ingin mendengar rekomendasi pendekatan yang baik. Mungkinkah hal ini dapat dicapai dengan memanipulasi beberapa visualisasi umum dengan cara yang rumit?

EDIT: Berdasarkan masukan dari ee2Dev, saya akan membuat 4 baris, bukan 2, menangkap panggilan/teks masuk dan keluar secara terpisah. Mengenai perincian, akan lebih baik jika visualisasi dapat menangkap data satu minggu dalam interval 5 menit (satu pesan teks sama dengan 5 menit berbicara dan panggilan 48 menit akan dibulatkan menjadi panggilan 50 menit). Jumlahnya adalah 7*24*12 = 2016 kemungkinan interval, yang tampaknya masuk akal. Mungkin interval 10 menit akan lebih cocok daripada interval 5 menit, tapi saya rasa kodenya dapat dengan mudah disesuaikan untuk itu. Sesuatu yang belum saya tunjukkan adalah bagaimana seharusnya tengah malam ditandai untuk menunjukkan hari mana yang aktif dan mana yang tidak.

Di bawah ini adalah kode saya dan data sampel saya:

// 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="/idtipsy.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");


 }

person pir    schedule 06.03.2015    source sumber
comment
Pertama-tama: pilihan visualisasi sepertinya tidak bagus: panggilan atau teks masuk dan keluar digambar dalam urutan yang sama, Pertama saya sarankan Anda memisahkannya menjadi empat urutan. Bagaimana seharusnya algoritma memilih menggambar jika ada banyak panggilan masuk dan keluar dalam satu hari. Isi separuh wilayah dengan warna biru muda dan separuh lainnya dengan biru tua? Interleave terang dengan biru tua? Kedua, pastikan untuk menunjukkan kepada pemirsa jam berapa yang digambarkan: Saya tidak melihat di mana tanggal 1/1/2015 berakhir atau di mana tanggal 5/1/2015 dimulai? Apakah ada tanggal 2 - 4 di antaranya atau hanya ditayangkan 2 hari saja?   -  person ee2Dev    schedule 06.03.2015
comment
Anda dapat memilih 4 grafik terpisah karena lebih cocok. Alternatifnya juga menggunakan empat visualisasi tampilan kalender bl.ocks.org/mbostock/4063318 dan sebagai ganti mengisi sepanjang hari dengan satu warna, buat kotak harian 24x24 dan gambar 1 garis vertikal untuk setiap jam, jika diskritisasi jam cukup granular   -  person ee2Dev    schedule 06.03.2015
comment
Terima kasih atas komentarnya. Aku sangat setuju. Hasil akhirnya seharusnya menjadi 4 baris. Data akan menampilkan hari berturut-turut sehingga menjadi tanggal 1 hingga tanggal 5. Saya telah memikirkan cara mengilustrasikan perubahan dalam beberapa hari (misalnya dengan memikirkan garis hitam saat melewati tengah malam), namun saya masih bertukar pikiran tentang cara membuatnya sesuai dengan visualisasi keseluruhan. Saya akan memperbarui teks aslinya.   -  person pir    schedule 06.03.2015
comment
rincian waktu berapa yang ingin Anda gambarkan? telepon ya/tidak per jam? setiap 30 menit?   -  person ee2Dev    schedule 06.03.2015
comment
Lihat teks yang diperbarui. Apakah menurut Anda interval 5 menit dalam seminggu terlalu ambisius?   -  person pir    schedule 06.03.2015
comment
Anda bisa melakukannya, tetapi jika Anda hanya menggunakan lebar 1 piksel per interval, Anda memiliki lebar total 2016px + mari kita 30px untuk label!   -  person ee2Dev    schedule 06.03.2015
comment
Hehe, benar. Kurasa aku tidak berpikir. Akan menarik untuk melihat apakah orang tersebut aktif dengan panggilan 48 menit atau hanya panggilan yang berlangsung 2 menit. Mungkin pilihan lain adalah melakukan interval 1 jam dan kemudian memberi kode warna pada interval tersebut tergantung pada aktivitasnya?   -  person pir    schedule 06.03.2015


Jawaban (1)


Untuk memberi Anda titik awal, gunakan kode ini dan mulai dari sana.

<!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>

dan di sini file 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

Dan ini JSFiddle: http://jsfiddle.net/ee2todev/6u0a0qnw/ Anda mungkin ingin hapus sumbu y, ganti dengan label, format sumbu x...sesuaikan warnanya, dll.

person ee2Dev    schedule 06.03.2015
comment
Terima kasih, sepertinya itu titik awal yang bagus :) Bisakah Anda menjelaskan secara singkat lebih detail tentang fungsi 3 baris kode ini? 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; })); - person pir; 09.03.2015
comment
Beberapa baris sebelumnya, saya mendefinisikan tiga variabel: colorOf, x dan y. Masing-masing variabel menunjuk ke suatu fungsi, khususnya fungsi skala. Skala adalah fungsi yang memetakan dari domain masukan ke rentang keluaran. Kisaran setiap skala telah ditetapkan di atas - jadi dalam tiga baris ini saya menetapkan domain yang benar. - person ee2Dev; 09.03.2015
comment
Jadi baris pertama menetapkan domain menjadi array dengan tipe berbeda dari data Anda (['inc_call', 'out_text', 'out_call', 'inc_text']. Nilai-nilai ini ingin Anda petakan ke koordinat y yang berbeda. Baris kedua menetapkan waktu minimum dan maksimum untuk menjadi domain x. Yang terakhir memetakan semua tipe ke warna. Perhatikan bahwa y dan colorOf memiliki domain yang sama (array dengan tipe berbeda) namun rentang berbeda (koordinat y atau warna) - person ee2Dev; 09.03.2015
comment
Anda mungkin melihat dokumentasi timbangan d3, lalu Anda dapat dengan mudah menyesuaikannya. - person ee2Dev; 09.03.2015