I'm posting there because I couldn't find something on other post or on google.
http://jsfiddle.net/CUQaN/9/
As you can see on the JS fiddle, I have a line chart with circle on each point.
I want to update this chart with new data. The problem is that I can receive less or more point than I already have on the graph. For example, I can have 8 point on my line chart and then when I'm updating the chart, I can have just 4, or even 15 point. And my circle are not updating properly because I'm just changing the value of the circle which already exist.
But I really don't know how to update them properly.
I can have that data sometimes :
var data = [
{"date":"4-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"3-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"2-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"1-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"30-Apr-12","close":Math.random()*354.98,"open":Math.random()*424.56},
{"date":"27-Apr-12","close":Math.random()*24.00,"open":Math.random()*253.89},
{"date":"26-Apr-12","close":Math.random()*490.70,"open":Math.random()*215.54},
{"date":"25-Apr-12","close":Math.random()*42.00,"open":Math.random()*351.23},
{"date":"24-Apr-12","close":Math.random()*210.28,"open":Math.random()*20.23},
{"date":"23-Apr-12","close":Math.random()*20.70,"open":Math.random()*368.34},
{"date":"20-Apr-12","close":Math.random()*412.98,"open":Math.random()*42},
{"date":"19-Apr-12","close":Math.random()*26.44,"open":Math.random()*20.56},
{"date":"18-Apr-12","close":Math.random()*48.34,"open":Math.random()*356.45},
{"date":"17-Apr-12","close":Math.random()*26.44,"open":Math.random()*20.56},
{"date":"15-Apr-12","close":Math.random()*48.34,"open":Math.random()*356.45},
];
And just that data other times : (more or less)
var data = [
{"date":"4-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"3-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"2-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"1-May-12","close":Math.random()*568.13,"open":Math.random()*35.12},
{"date":"30-Apr-12","close":Math.random()*354.98,"open":Math.random()*424.56},
];
Is someone can help me please ?
Thanks a lot !
It might be better to remove the old points and add the new ones rather than trying to move them. To do this you can use an id function to make the points unique - see here
A small example:
svg.selectAll("circle")
.data(myData, function(d) { return d.x; })
.enter()
.append("circle");
The important part here is that points are identified by their x-value, rather than their index in the data point array. Infact this might help in your current situation as the points will only move up/down and not side to side.
Related
I am trying to plot a multiline d3 chart. I have created a method which should take a new dataset and try to plot it in the same d3 frame for new data update changes (possibly filters).
The first draw works fine but the next draw (mocked data: which is a slice of the previous data and few manipulated values) is not showing correct is crossing the x axis.
[See Image below]
Also the starting origin is missing a tick which should also be 2010 in this example
I also want to create few more lines if there is more datapoints in the future which should be dynamic. Current model is {date, actual, projected}, More expected is mean or difference which will only be shown on trigger.
Any help would be appreciated.
Here is a Stackblitz https://stackblitz.com/edit/angular-rhr39p
References:
Animated line chart: http://bl.ocks.org/atmccann/8966400
Multiline chart: https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91
Dataset updates: https://bl.ocks.org/d3noob/7030f35b72de721622b8
Please keep just one problem per question here at Stack Overflow. This answer will deal with problem #1, consider asking separate questions for the other problems.
The issue here is just your enter/update methodology, that is not correct and. Stick with the idiomatic D3, which is along these lines:
const update = this.svg.selectAll('.records')
.data(records);
const enter = update.enter().append('g')
.attr('class', 'records');
Then, you append new paths using enter and update those paths using update.
You can also ditch the groups and create enter/update/exit selections for the paths directly. That will make your code simpler.
Here is the forked code: https://stackblitz.com/edit/angular-lyd79t?file=src%2Fapp%2Flinechart%2Flinechart.component.ts
After making several bar charts using enter, update, exit method in D3js, I wanted to try the same with a pie chart. I thought I applied selections correctly, but the pie chart won't update with the new data in JSON. I looked for similar examples online, but couldn't find one which involved an .on("click" method. I want users to compare the lifespans of humans and animals using a donut chart. I'm trying to implement the search tool through the database of animals right now.
here's what a data object looks like for the query Goat:
[{"Animal":"Male","Life_Span":73},{"Animal":"Goat","Life_Span":10}]
I'm having trouble with this code in particular:
var pie = d3.pie()
.sort(null)
.value(function(d) { return d.Life_Span; });
//code for accessing data, etc
//enter remove selections
var path = svg.selectAll("path")
.data(pie(newdata))
var enterdata =
path.enter().append("path")
.attr("d",arc)
path.exit().remove()
enterdata.exit().remove()
I posted the full code on Plunkr here: http://plnkr.co/edit/3QSAPxQpju63tIXRd9p7?p=preview
A few weeks into learning d3js, I'm still struggling with enter,update exit selections even after reading many tutorials on the subject. I would really appreciate any help. Thanks
In D3 v4.x, you need to merge the update and enter selections:
var enterdata = path.enter()
.append("path")
.merge(path)
.attr("d",arc)
You don't need an exit selection because your data array has always 2 objects: except for the first time, your enter selection is always 0, and your exit selection is always 0.
I took the liberty of colouring the paths in different colours, according to their indices:
.attr("fill", (d,i) => i ? "teal" : "brown");
Here is your updated plunker: http://plnkr.co/edit/l6OzmxVfid9Cj7iv7IMg?p=preview
PS: You have some problems in your code, which I'll not change (here I'm only answering your main question), but I reckon you should think about them:
Don't mix jQuery and D3. You can do everything here without jQuery
Don't load all your CSV every time the user chooses an animal. It doesn't make sense. Instead of that, put the click function inside the d3.csv function (that way, you load the CSV only once).
I'm new to StackOverflow and I just started using D3.
I need to show the values on a map. I saw this question that is very similar to what I should do.
What I'd like is to color the countries based on the values in the column Date to a CSV and based on selected year by user (radio button).
How can I do that?
I created a gray color scale and have included them in an array, then I created a method chooseColor(value) that returns the correct color based on the value of the country in that year.
I think it is not the most efficient method to do this thing...
Also in my CSV there are not all the countries present in the European Union. For example, I have no data on Russia so I "turned off" some countries putting an if inside the event on mouseover.
But I would also cut part of Russia in the map in order to enlarge the known countries. How can I do also that thing?
I looked at these examples: Choropleth and Threshold Choropleth by Mike Bostock on bl.ocks.org but I have not understand how to color the countries...
(I wanted to put links but I can't post more than 2 links because of my low reputation)
This is my code.
I apologize for my bad English. Thank you all,
Pier
EDIT
I admit I did not understand some things in your code.
Why I need events on mouseover and mouseout? And what are hover and rhover? I thought they were events related to this question. But in my case I don't need it, no?
Use array_values or d is the same, right? Does not change if I use d or array_values, right? It is a stupid question but it confused me.
I modified the makemap method in this way. I understand correctly how to use your code?
function makemap(error, europe, dessease) {
dess = dessease.slice();
counties = topojson.feature(europe, europe.objects.collection);
vector = svg.selectAll("path")
.data(counties.features)
.enter()
.append("path")
.attr("class", "county")
.attr("id", function(d) {
return "coun" + d.properties.indx;
})
.attr("d", path)
.style("fill", function(array_values) {
return color(array_values[d.country]);
});
In this case there is an error concerning d, of course. Sorry, I do not know where I'm wrong...
The country's color will depend on a value. So the color IS a function of "value". To do that you must to define a range of color based on your values:
var color = d3.scale.linear()
.domain([mn,mx]) // <--- min and MAX of your value
.range(["#ffffff","000000"]);
then define the color of your country:
svg.selectAll(".county")
.style("fill", function(array_values) {
return color(array_values[d.country]);
});
Must-Read: Jerome Cukier - d3: scales, and color
I've been attempting to learn better visualization with node.js and the mapbox library.
Using this example here: Running Map Example
I'd like to add a graph of speed, and allow a user to click on a node, and see data about that position in a little popup - For today, I just want to get speed working.
It seems to be a recursive algorithm, so I need to implement variables to store the previous position and time, but I've ran into three problems:
I don't know how to use this date format: "2015-01-19T21:24:20Z" or Chroniton's parsing of it to generate a subtractable number to get the difference in time.
I don't know how to get the distance between two points using the code given, I could simply do sqrt((.x(point1) - .x(point2)) + (.y(point1) + .y(point2)), but I'm not sure how coordinates are stored or parsed in this example.
I don't know where to calculate the speed. It seems like the coordinates are only defined after the graphs are displayed, since the coordinates aren't used in the graphics. I am probably wrong, but I need some direction.
Here is what I have now:
Using the elevation display as my template, I think I have made it able to display the line by adding in the following three snippets:
Setting the scale:
var speed = d3.scale.linear()
.range([height, 0])
.domain([0, d3.max(dataRet, function(d) {
return d[1][2];
})]);
Adding in the line, with data:
var SpeedLine = d3.svg.line()
.x(function (d) { return x(d[0]); })
.y(function (d) { return speed(d[2])})
Displaying the line:
svg.append('path')
.datum(dataRet)
.attr('class', 'speed-line')
.attr('d', speedLine);
I know I have to add in a speed function similar to this psudocode:
var dt = chroniton.domain(Time1, Time2)
var speed[i] = LongLat(previousPoint).distanceto(currentPoint)/dt
And on the popup box:
dt.format(something to do with time formatting)
Note 1:, I changed the name of the function datePlaceHeart to dataRet since I'll be adding new things to do it, and datePlaceHeartSpeedStuffAndThings was getting a bit long ;)
Note 2: I haven't been able to start the pop-up because I haven't figured out how to calculate speed using the given data, and well, it seems kinda silly to do the easy one first. (With my luck, its actually not easy)
Please help? Here is my edited code in full (Edited index.js):
Code
First of all, let me be clear on this: i'm a d3 newbie!
So, i have a chart based on utc time domain. the domain is one of this: 1 day | 3 days, and I can switch from one to the other with a user action.
Refreshing / transitioning the x to represent 24hs to 72hs is working properly, but I'm having difficulties to update the elements that are already in the chart. Some how it seems that after changing the domain .data() .enter() won't actually enter (so my attr don't get updated).
This is a jsbin with the full example of my problem. Any clues?
You need to follow this series of examples very carefully.
Here is the problem code corrected ...
group.enter()
.append('g')
.attr('class', 'flight');
group.attr('transform', function (trip) {
return 'translate(' + hourDomain( Math.min.apply(null, _.map(trip.legs, 'departureDateTime'))) + ', 60)';
});
The problem is that you are applying the positioning to the enter selection only: only new nodes. After the first call, the enter selection is always empty because there are no new nodes. The linked examples will explain it.