【问题标题】:Loading D3.js data from a simple JSON string从简单的 JSON 字符串加载 D3.js 数据
【发布时间】:2013-03-23 18:46:08
【问题描述】:

图库中的大多数示例都从 TSV 文件加载数据。

如何转换以下内容以使用本地 json 变量而不是 TSV 数据?

d3.tsv("data.tsv", function(error, data) {

    var myEntitiesJson = getEntitiesJson(); // <------ use this instead of "data"
    data.forEach(function(d) {
        d.frequency = +d.frequency;
    });

    x.domain(data.map(function(d) { return d.letter; }));
    y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

    ...

    svg.selectAll(".bar")
        .data(data)     // <----- bind to myEntities instead
}

据我所知,我只需要对我的 entityJson 做一些事情,以便对其进行 data-fy 以便图表可以绑定到它。

更新

我正在取得一些进展。我从 JSON 插入我的实体,图表开始呈现新的形状。

目前以下代码中断:

svg.selectAll(".bar")
    .data(myEntities)  // <-- this is an array of objects
    .enter().append("rect")

这是导致:

错误:属性 y="NaN" 的值无效

错误:属性 height="NaN" 的值无效

【问题讨论】:

  • 嘿,Cees,这似乎是可折叠树的特定解决方案?
  • 使用本地 JSON 变量而不是外部源。
  • 这也有助于发布有问题的 JSON。

标签: d3.js


【解决方案1】:

用于远程数据.json 替换:

d3.tsv("data.tsv", function(error, data) {...}

与:

d3.json("data.json", function(error, data) {
    console.log(data); // this is your data
});

对于本地数据:

var myData = { {date:'2013-05-01', frequency:99},
               {date:'2013-05-02', frequency:24} };

function draw(data) {
    console.log(data); // this is your data
}

draw(myData);

【讨论】:

  • 所以,在我下面的 d3 示例中,看起来图表轴使用 x.domain(data.map(...)) 映射到数据集,然后使用 svg.selectAll( “.bar”).data(data).. 从您的示例中不清楚我如何改装 jason sn-p 来代替数据的使用方式。 draw(myData) 如何神奇地知道哪些属性用于哪个轴等?
  • console.log(data); // this is your data 替换为您的function(error, data) 正文,例如x.domain(data.map(function(d) { return d.letter; })) 等。
【解决方案2】:

没有一种简单的方法可以对任何给定的 json 进行数据化,因为并非所有 json 对象都是相同的形状

我所说的形状是指数据的组织方式。例如,'{"foo" : 1, "bar" : 2}''{"names" : ["foo", "bar"], "values" : [1, 2]}' 都可以用于存储相同的数据,但是一个将所有内容存储在一个对象中,其中对象键对应于数据点的名称,另一个使用单独的数组来存储名称和值, 对应的条目有一个共同的数组索引。

但是,您可以通过一个通用的过程将 json 转换为数据。首先,您需要解析 json。这可以使用 javascript 标准的 JSON 对象来完成。如果已经上传到客户端,请使用JSON.parse(myJson) 从您的 json 对象中获取数据。 d3.json(my/json/directory, fn(){}) 可以加载和解析您的 json,因此如果您从服务器上的其他位置加载它,这可能是将 json 放入对象的更好方法。

一旦您将 json 打包到 javascript 对象中,您仍然需要对其进行数据处理,这将取决于您的数据。它所期望的 d3 是某种形式的数组:[dataPoint1, dataPoint2, ...]。对于我上面给出的两个例子,你想要的数组看起来像这样:

[{'name' : 'foo', 'value' : 1}, {'name' : 'bar', 'value' : 2}]

我的数组中每个数据点都有一个元素,具有两个属性:valuename。 (在您的示例中,您需要属性 letterfrequency

对于我的每个示例,我将使用不同的函数来创建数组。与这条线的共同点:

var rawData = JSON.parse(myJson);

我的第一个 json 可以用这个函数打包:

var key;
var data = [];

for(key in rawData){
    if(rawData.hasOwnProperty(key)){
        data.push({'name' : key, 'value' : rawData[key]});
    }
}

对于第二个示例,我想遍历对象的每个属性,namesvalues。我的代码可能如下所示:

var i;
var data = [];

for(i = 0; i < rawData.names.length; i++){
    data.push({'name' : rawData.names[i], 'value' : rawData.values[i]});
}

这两个都将产生我的原始 JSON 的数据版本版本,然后我可以在 d3 中使用它。

【讨论】:

  • 感谢您的回复。我有一段时间没有使用 d3,但计划很快再使用它,并将尝试这个策略!
  • 作为一个已经阅读了关于将 json 数据映射到 d3 的所有不同教程的人,这是迄今为止我所见过的信息量最大的文章。来自我的 +1。
  • 嗨!当我试图从变量中读取数据而不是从“json文件”中读取时,我遇到了类似的问题。 以下示例bl.ocks.org/mbostock/5944371 我成功地改变了这一点,以防数据简单使用,像这样...... for(i = 0; i 但这里有点复杂。
  • @amarinderthind 你需要做什么取决于你的数据结构。通常,对于分区布局之类的东西,您需要为布局函数上的“children”方法提供一个函数,该函数将在提供该节点时返回给定节点的子节点。如果您需要帮助确定如何做到这一点,请随意发布一个不同的问题,说明您的问题的具体情况。
  • @ckersch,我完成了定义根目录时出现问题......但现在完成了......以下列方式......以防其他需要......函数绘制(数据) {根=数据; console.log("数据"); // 这是你的数据分区 .value(function(d) { return d.size; }) .nodes(root) .forEach(function(d) { d._children = d.children; d.sum = d.value ; d.key = key(d); d.fill = fill(d); }); } 绘制(数据);
【解决方案3】:

对于D3js v2v3(不确定是哪一个)。

声明你的数据集

var dataset = { 
    "first-name": "Stack",
    "last-name": "Overflow",
}; // JSON object
var dataset = [ 5, 10, 15, 20, 25 ]; // or array

作为stated by the doc,您可以使用:

数字或对象数组,或返回值数组的函数

绑定

d3.select("body").selectAll("p")
    .data(dataset)
    .enter()
    .append("p")
    .text("New paragraph!");

更多解释Scott Murray's D3's tutorial#Binding data

data() 函数适用于一个选择,更多信息可以在官方文档中找到:selection.data([values[, key]])

【讨论】:

  • 在我提供的示例中,数据集(来自 data.tsv)和轴之间进行了映射。简单地将我的 json 对象替换为数据会因多种原因而中断。它不支持 .map 属性,并且使用 .data() 绑定它会引发异常“无法读取未定义的属性'长度'”..这就是为什么我评论说必须对我的对象做一些事情才能做到这一点可映射到图表。这就是我不清楚的地方,特别是在上面的例子中。
  • 这个例子暂时不起作用。给出的第一个示例将dataset 定义为对象,而不是数组。 d3 需要将数据格式化为数组,因此需要将dataset 对象转换为数组,然后才能将其绑定到所选内容。
  • @ckersch 这个答案使用了d3js v2v3(不确定),有一个新的v4 可用,因此API 发生了变化。您介意发布最新版本的有效答案吗?
【解决方案4】:

您可以将 json 更改为将数据分配给全局值的 javascript 文件。以https://bl.ocks.org/d3noob/5028304为例:

发件人:

<script>
.....
// load the data
d3.json("sankeygreenhouse.json", function(error, graph) {

    var nodeMap = {};
    graph.nodes.forEach(function(x) { nodeMap[x.name] = x; });

收件人:

<script src="graphData.js"></script>
<script>
.....
    var nodeMap = {};
    graph.nodes.forEach(function(x) { nodeMap[x.name] = x; });

请注意,我们已经消除了对回调的需求。

json 文件是“sankeygreenhouse.json”:

{
"links": [
  {"source":"Agricultural Energy Use","target":"Carbon Dioxide","value":"1.4"},

现在,在“graphData.js”中:

var graph = {
   "links": [
      {"source":"Agricultural Energy Use","target":"Carbon Dioxide","value":"1.4"},

【讨论】:

    【解决方案5】:

    只需将数据更改为对象数组,如下所示:

    let data = [{"apples":53245,"oranges":200},{"apples":28479,"oranges":200},{"apples":19697,"oranges":200},{"apples":24037,"oranges":200},{"apples":40245,"oranges":200}]
    

    并注释掉d3.tsv("data.tsv", function(error, data) {...

    【讨论】:

      【解决方案6】:

      为什么不按照 Rob here 的描述简单地将您的 json 转换为 tsv?

      d3 需要数据,或者换句话说,需要特定格式的数据:tsv。解决问题的最简单方法是将数据从 json 格式化为 tsv,这可以使用 Rob 的 cmets 轻松完成。

      【讨论】:

      • d3 不需要格式化为 tsv 的数据,它需要格式化为数组的数据。它包含一个用于将 tsv 数据转换为数组的实用函数,但将 JSON 直接转换为 javascript 数组而不是将其转换为 tsv 然后将 tsv 转换为数组更简单。
      • Json 是一个很好的标准,可能 OP 需要回答才能使用 JSON。
      猜你喜欢
      • 1970-01-01
      • 2018-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-19
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多