2014-05-09 24 views
6

Tôi sử dụng thư viện wordcloud của Jason Davies cho d3 (https://github.com/jasondavies/d3-cloud) và vấn đề của tôi là các từ trong đám mây trùng nhau.Chồng chéo trong d3 wordcloud

Tôi biết rằng đã có các câu hỏi liên quan đến vấn đề này về tràn ngăn xếp (và các trang web khác), nhưng không có điều nào trong số này giúp ích trong trường hợp của tôi.

Trong ví dụ sau tôi sử dụng ví dụ đám mây từ trang web của Jason Davies' và thay đổi chỉ có một vài điều:

  • tôi đọc những lời của tôi và kích thước của chúng từ một tập tin bên ngoài.
  • Tôi đặt xoay thành 0. Góc quay dường như không tạo nên sự khác biệt.
  • Tôi đã nhận xét phông chữ "Tác động", để loại trừ bất kỳ sự cố nào khi tải phông chữ. (Nó làm cho có sự khác biệt trong hai mặc dù.)

Đây là mã của tôi:

<!DOCTYPE html> 
<meta charset="utf-8"> 
<body> 
<script src="d3.js"></script> 
<script src="d3.layout.cloud.js"></script> 
<script> 
    d3.tsv("testdata.txt", 
    function(error, data) { 

    var fill = d3.scale.category20(); 



    d3.layout.cloud().size([300, 300]) 
     .words(data) 
     .padding(1) 
     .rotate(function(d) { return 0; }) 
    // .font("Impact") 
     .fontSize(function(d) { return d.size; }) 
     .on("end", draw) 
     .start(); 

    function draw(words) { 
    d3.select("body").append("svg") 
     .attr("width", 300) 
     .attr("height", 300) 
     .append("g") 
     .attr("transform", "translate(150,150)") 
     .selectAll("text") 
     .data(words) 
     .enter().append("text") 
     .style("font-size", function(d) { return d.size + "px"; }) 
    // .style("font-family", "Impact") 
     .style("fill", function(d, i) { return fill(i); }) 
     .attr("text-anchor", "middle") 
     .attr("transform", function(d) { 
      return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; 
     }) 
     .text(function(d) { return d.word; }); 
    } 
    } 
) 

</script> 

Các TestData trông như thế này (các thông tin màu không được sử dụng trong ví dụ):

word size color 
der 39 #a9a9a9 
die 37 #a9a9a9 
und 30 #a9a9a9 
athenischen 29 #a9a9a9 
Die 29 #a9a9a9 
eine 28 #a9a9a9 
, 27 #a9a9a9 
einer 26 #a9a9a9 
attischen 26 #a9a9a9 
liberalen 26 #1e90ff 
zur 25 #a9a9a9 
athenische 24 #a9a9a9 
christliche 23 #a9a9a9 
attische 23 #a9a9a9 
_START_ 22 #a9a9a9 
reinen 22 #a9a9a9 
englischen 21 #a9a9a9 
oder 21 #a9a9a9 
-- 21 #a9a9a9 
radikalen 21 #a9a9a9 
Q*M 21 #a9a9a9 
Q*M 21 #a9a9a9 
christlichen 20 #a9a9a9 
schöne 20 #1e90ff 
repräsentativen 20 #a9a9a9 
sozialen 20 #a9a9a9 
hellenische 19 #1e90ff 
modernen 19 #a9a9a9 
radikale 19 #a9a9a9 
griechische 19 #a9a9a9 
- 18 #a9a9a9 
schönen 18 #1e90ff 
alle 18 #a9a9a9 
radicalen 18 #a9a9a9 
als 17 #a9a9a9 
neuen 17 #a9a9a9 
perikleischen 16 #a9a9a9 
bürgerlichen 16 #a9a9a9 
Namen 16 #1e90ff 

Nếu tôi chạy tập lệnh js với dữ liệu thử nghiệm thì đám mây từ của tôi xuất hiện với các chồng chéo. Đôi khi nó chỉ xảy ra sau một vài lần tải lại, nhưng nó khá thường xuyên.

Những người khác đã báo cáo cùng một vấn đề và nhận thấy rằng nó liên quan đến việc sử dụng phông chữ web hoặc bỏ qua thông số xoay. Điều này không áp dụng trong ví dụ của tôi.

Tôi nghi ngờ rằng nó có thể liên quan đến thực tế là có nhiều từ cho kích cỡ canvas, tuy nhiên, tôi cũng đã thử nghiệm nơi tôi tăng kích thước canvas một cách đáng kể và nó vẫn xảy ra (mặc dù ít thường xuyên hơn, như ngẫu nhiên vị trí của các từ làm cho nó ít có khả năng). Ngoài ra, bạn có thể thấy rằng một số từ không được hiển thị ở tất cả do kích thước canvas nhỏ. Tại sao để lại một số và tạo chồng chéo cho người khác? Vì vậy, tôi nghĩ vấn đề nằm ở nơi khác.

Bất kỳ ý tưởng nào?

Cảm ơn!

+0

Đồng ý rằng có những khó khăn. Tuy nhiên, chơi một chút với kích thước (bố cục và svg) và họ phông chữ, có thể chỉ đạt được các chồng chéo thường xuyên và tương đối nhẹ (nhưng mức độ trùng lặp có thể chấp nhận được một chút chủ quan). Trong mọi trường hợp, đây là một [plunk] (http://plnkr.co/edit/1In5m9Ot7nUPrNULOOYv?p=preview) mà tôi tạo ra để chơi với nó. Ít nhất, tôi tin rằng những chiều hướng này được cải thiện về việc loại trừ các từ ... có vẻ như hầu hết trong số chúng đều có (mặc dù chúng cần tất cả ở đó). – FernOfTheAndes

+0

Vâng, cảm ơn bạn. Bạn đã thay đổi kích thước và phông chữ theo như tôi thấy?Nó hoạt động khá ổn cho ví dụ này. Tuy nhiên, tôi thực sự muốn giải quyết vấn đề nói chung. Tôi thực sự khá ngạc nhiên khi nó xảy ra vì toàn bộ quan điểm của bố cục đám mây từ nên tránh trùng lặp và tôi thấy rất nhiều lời khen ngợi cho nó. – spaebrun

+0

Bạn nói đúng. Đó là tất cả những gì tôi đã làm. Và đồng ý với bạn, một giải pháp chung là những gì cần thiết. Chúng ta có thể thiếu một cái gì đó ... Tôi không có thời gian để nghiên cứu sâu về nó quá sâu. Bạn cũng có thể viết một email tới [Jason] (http://www.jasondavies.com). – FernOfTheAndes

Trả lời

14

Tôi đã tự hỏi Jason Davies và đó thực sự là một sai lầm khá đơn giản: Bạn phải chỉ định hàm truy cập văn bản trong câu lệnh đầu tiên (không chỉ trong hàm "vẽ"). Nó hoạt động nếu bạn thêm một dòng như thế này:

d3.layout.cloud().size([300, 300]) 
    .words(data) 
    .padding(1) 
    .rotate(function(d) { return 0; }) 
// .font("Impact") 
    .text(function(d) { return d.word; }) // THE SOLUTION 
    .fontSize(function(d) { return d.size; }) 
    .on("end", draw) 
    .start(); 
+0

đệm hoạt động. thanks – Adeel

+0

Không, nó chỉ thay đổi kích cỡ phân bố của các từ trên màn hình và làm cho hộp thậm chí nhỏ hơn gây chồng chéo hơn – dresh

+0

* PHÁT HÀNH COMMON: * không neo văn bản SVG vào giữa, '.attr (" text-anchor "," vấn đề giữa ")' –

0

Tôi đã thử một mẫu để bạn có thể fiddle với, hãy có một cái nhìn. wordcloud without overlap

cơ bản:

<div id="cloud"></div> 

// First define your cloud data, using `text` and `size` properties: 


var fill = d3.scale.category20(); 
var words = { 
"Battery Related": "52382", 
"Billing": "52412", 
"Break Related": "52490", 
"Chain Related": "52471", 
"Clutch Related": "52468", 
"Dealer attitude": "52488", 
"Electrical Related": "52352", 
"Engine Related": "52446", 
"Handle Bar Related": "52486", 
"Happy": "52472", 
"Jerking": "52325", 
"Jerking Problem": "52325", 
"Low Mileage": "52489", 
"Noise": "52462", 
"Poor Pickup": "52406", 
"Running Off": "52242", 
"Service Quality": "52488", 
"Silencer Problem": "52468", 
"Starting Trouble": "52490", 
"Suspension Related": "52365", 
"Vehicle Noise": "52467", 
"Vibration": "52463", 
"Washing": "52488" 
}; 
var max_freq = 52490; 
var cloudwords = ["Battery Related", "Billing", "Break Related", "Chain Related", "Clutch Related", "Dealer attitude", "Electrical Related", "Engine Related", "Handle Bar Related", "Happy", "Jerking", "Jerking Problem", "Low Mileage", "Noise", "Poor Pickup", "Running Off", "Service Quality", "Silencer Problem", "Starting Trouble", "Suspension Related", "Vehicle Noise", "Vibration", "Washing"]; 
var url = 'http://xxx.yyyy.zz.ww/?q=abc/'; 
var width = 800, 
height = 800; 

var leaders = cloudwords 
.map(function(d) { 

return { 
    text: d, 
    size: 5 + (words[d]/max_freq) * 0.9 * 30 // *the size of the "box" occupied by each word. has no relation to text size. 
}; 
}) 
.sort(function(a, b) { 
return d3.descending(a.size, b.size) 
}); 

var leaderScale = d3.scale.linear().range([1, 20]); // *scale range to plot the relative sizes of the words. 

leaderScale.domain([d3.min(leaders, function(d) { 
return d.size; 
}), 
d3.max(leaders, function(d) { 
return d.size; 
}) 
]); 

// Next you need to use the layout script to calculate the placement, rotation and size of each word: 

d3.layout.cloud().size([width, height]) 
.words(leaders) 
.padding(0) //fiddle with padding here, does not really have any effect on overlap. 
.rotate(function() { 
return ~~0; //to keep the words horizontal 
}) 
.font("Impact") 
.fontSize(function(d) { 
return d.size; 
}) 
.on("end", drawCloud) 
.start(); 

function drawCloud(words) { 
d3.select("#cloud").append("svg") 
.attr("width", width) 
.attr("height", height) 
.attr("text-align", "center") 
.append("g") 
.attr("transform", "translate(" + [width >> 1, height >> 1] + ")") //for transalting words to their different postions. 
.selectAll("text") 
.data(words) 
.enter().append("text") 
.style("font-size", function(d) { 
    return leaderScale(d.size) + "px"; //used scale to resize words to a linear scale. 
}) 
.style("font-family", "Impact") 
.style("fill", function(d, i) { 
    return fill(i); 
}) 
.attr("text-anchor", "middle") 
.attr("transform", function(d) { 
    return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; 
}) 
.text(function(d) { 
    return d.text; 
}) 
.on("click", function(d, i) { 
    window.open(url + d.text); 
}); 
} 

// set the viewbox to content bounding box (zooming in on the content, effectively trimming whitespace) 

var svg = document.getElementsByTagName("svg")[0]; 
var bbox = svg.getBBox(); 
var viewBox = [bbox.x, bbox.y, bbox.width, bbox.height].join(" "); 
svg.setAttribute("viewBox", viewBox);