D3基于两个不同的数据集更改元素? [英] D3 change elements based on two different datasets?

查看:113
本文介绍了D3基于两个不同的数据集更改元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是d3的新手,没有javascript专家。我发现了类似的问题,但没有一个是我正在寻找的。
我有两个csv文件,一个有学校数据,看起来像这样
id,名称,经度,纬度



其他csv有网络数据



id netId (这是连接的其他学校id)

我已将学校数据绑定到地图上的圈子。我想做的是点击,找到每个连接的学校,并根据他们有多少连接在地图上转换他们的圈子。



我假设这将需要一系列for循环,但我不确定最好的方法。
目前,跳过所有的地图创建的东西,我有这样:

  var currData = []; 

d3.csv(network.csv,function(networkData){
d3.csv(schoolData.csv,function(data){

//创建圈子

var circle = svg.selectAll(circle)
//绑定数据
.data(data)
.enter
.append(circle)
.attr(cx,function(d){
return projection([d.lon,d.lat])[0];
})
.attr(cy,function(d){
return projection([d.lon,d.lat])[1];
})

//初始样式的圆(最终会将它移动到类中)
.attr(r,5)
.style(fill,orange)
.style(opacity,0.75)



//点击
.on(click,function(d){


for(i = 0; i = networkData.length; i ++){
if(d.id == networkData [i] .id){
currData.push({netId:networkData [i] .netId,
hits networkData [i] .hits}
)}
};

这是返回netId和命中,如果我记录到控制台的for循环,似乎不能访问currData外的for循环。我不知道为什么。
我也不确定最好的方法来取每个后续​​的netIds,并链接到学校的数据绑定到圈子元素。我使这更复杂比必要吗? D3有一个简单的方法这样做吗?



当地图上点击一个圆圈时,我需要找到所选学校网络中的学校id,然后根据匹配数量在地图上更改其圈子。非常像这个



数据如下:

 学校数据:

id,school,lon,lat
1,UC Berkeley,-122.250502,37.872855
2,UC Los Angeles,-118.445227,34.06886
3,Cal State Los Angeles,-118.168266,34.068232
4,University of南加州,-118.2866414,34.021801

网络数据:

id,netId,hits
193,220,1
193,229,5
193,226 ,1
193,49,1
124,226,11
124,201,1
278,175,7
341,227,1
341,310,2
341,135,1
101,201,1


解决方案

您希望能够基于其数据属性选择一个元素,最简单的方法是根据该数据为该元素提供一个类名。例如,所有的学校元素都可以基于他们在数据中的id,s-1,s-203等等。



当您从网络数据表中找到一行中引用的id时,很容易选择相应的元素并根据需要更改它。



下面是一个示例。我使用 Array.forEach()而不是一个for循环,但它是一个类似的想法,你有什么。我不太确定你是如何使用过滤的数据数组,以及为什么它不能为你工作,但希望这会让你开始:



http://fiddle.jshell.net/V5DCx/



但是,不是每次点击扫描净数据,它可能值得操作前面的数据,并将其包括在学校的数据对象。您可以使用 d3.nest 将网络数据分组为子数组基于id,然后通过学校数组排序一次,将正确的网络子数组附加到学校数据,然后将学校数据附加到您的d3图形。然后它将在你的函数(d)事件处理程序中等待。


I am new to d3 and no javascript expert. I've found similar questions, but none that are quite what I'm looking for. I have two csv files, one with school data that looks like this id, name, longitude, latitude

The other csv has network data

id, netId (this is other school ids that are connected), hits (this is basically how many connections are between the two schools)

I have the school data bound to circles on a map. What I'm trying to do is on a click, find each of the connected schools and transition their circles on the map based on how many connections they have.

I'm assuming this is going to need to be a series of for loops, but I'm not sure of the best way to do it. Currently, skipping past all the map creation stuff, I have this:

    var currData = [];

 d3.csv("network.csv", function(networkData){
    d3.csv("schoolData.csv", function(data) {

             //create the circles

             var circle = svg.selectAll("circle")
     //bind the data
                    .data(data)
                    .enter()
                    .append("circle")
                    .attr("cx", function(d) {
                        return projection([d.lon, d.lat])[0];
                    })
                    .attr("cy", function(d) {
                        return projection([d.lon, d.lat])[1];
                    })

                //initial style of circles (will move this into a class eventually)
                    .attr("r", 5)
                    .style("fill", "orange")
                    .style("opacity", 0.75)



            //on click 
                    .on("click", function (d) {


            for (i = 0; i<= networkData.length; i++) {
                    if(d.id == networkData[i].id) {  
                    currData.push({"netId": networkData[i].netId,
                                    "hits": networkData[i].hits}
                        )}
                    };

This is returning the netId and hits if I log it to the console within the for loop, but I can't seem to access currData outside of the for loop. I'm not sure why. I am also not sure of the best way to take each of the subsequent netIds and link them back to the school data bound to the circle elements. Am I making this more complicated than necessary? Does D3 have an easy way of doing this?

When a circle is clicked on the map, I need to find the id of schools in the network for the selected school and then make a change to their circles on the map based on the number of hits. Very much like this.

The data looks like this:

School Data: 

id,school,lon,lat
1,UC Berkeley,-122.250502,37.872855
2,UC Los Angeles,-118.445227,34.06886
3,Cal State Los Angeles,-118.168266,34.068232
4,University of Southern California,-118.2866414,34.021801

Network Data:

id,netId,hits
193,220,1
193,229,5
193,226,1
193,49,1
124,226,11
124,201,1
278,175,7
341,227,1
341,310,2
341,135,1
101,201,1

解决方案

If you want to be able to select an element based on its data attribute, the easiest way to do that is to give the element a class name based on that data. For example, all your school elements could have a class based on their id in the data, "s-1", "s-203", etc.

Then, when you find that id referenced in a row from your network data table, it is easy to select the corresponding element and change it however you want.

Here's an example. I'm using Array.forEach() instead of a for loop, but it is a similar idea to what you had. I'm not quite sure how you were using your filtered data array and why it wasn't working for you, but hopefully this will get you started:

http://fiddle.jshell.net/V5DCx/

However, instead of scanning through the net data on every click, it might be worth manipulating the data up front and including it in the school's data objects. You can use d3.nest to group the network data into sub-arrays based on the id, and then sort through the school array once, attaching the correct network sub-array to the school data before attaching the school data to your d3 graphics. Then it will be right there waiting in your function(d) event handler.

这篇关于D3基于两个不同的数据集更改元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆