dc.js heatmap expanding data - dc.js

I am trying to show machine states over time. Part of this is to reproduce/automate a report that used to be done by hand. It consists of coloring 2minute 'time slices' in Excel based on what the machine is doing.
(Sorry, not enough reputation to post a picture, but it is a classic heatmap where the state drives the color. Some non DC-JS fiddle: http://jsfiddle.net/ww6Lbnc5/4/)
I was able to generate most of what I want in the following jsfiddle:
http://jsfiddle.net/hwhfxz2t/14/
See fiddle for code.
The total state duration (for selected time frame) is shown in the pieChart, followed by the individual state lines and then the heatmap that people are used to. (the ZOOM and date selection buttons do not work in the fiddle but are there to select specific data ranges or zoom in if you like).
The line charts uses the original representation of the states, which consists of a time the state is entered and a duration.
In order to make the heat map work, I had to (I think) take the original data and convert it into individual minute chunks and mark them with a state. So for instance the original data specifying:
RUN state starting 14:30 for 300 seconds
becomes:
14:30=RUN, 14:31=RUN, 14:32=RUN, 14:33=RUN and 14:34=RUN
The code in lines 233-297 loops through the original data and generates a new one that does this. In cases where there is more than one state within a given minute, the last state survives.
This works okay but it seems that this code is exactly what is normally done in group().reduce(add,remove,init). But in this case I need to add multiple timeslots depending on the duration of a state.
Also, because it is now using a different crossfilter, maps do not update each other.
Here are my questions related to this:
Can I display a heatmap without supplying information for all individual
'cells'? (i.e. straddle cells based on a value, similar to rowspan in a table)
Can I add multiple values at once inside group().reduce()?
Is there an easy way to invert the yAxis so 0 is at the top?
When clicking a row in the heatmap, it selects a column and vice-versa?
I'm not sure if this should be in the crossfilter group. If so please ignore my rambling. If someone knows how to keep the charts linked by grouping better, please let me know.
--Nico

Concerning Question 3:
DC.js heatmaps currently do not support custom order functions on axis but there is a pull request that has been merged into the developing branch and should be accessible to the public soon.
You could manually edit the dc.js file to set the sorting in heatmaps to a custom function. In the latest (2.0.0-beta10) version it is the following line:
rowValues.sort(d3.ascending);
and accordingly
colValues.sort(d3.ascending);

Related

Google Sheets: How do I format a range to color a row if every cell in that row has matching data?

I want to make it so if all of the cells in a row has data that matches, it will automatically change the row's fill color to green.
Example of the desired visual effect, including my conditional formatting work-around to achieve the look
As you can see in the image, the rows that have empty cells are not colored green.
Some other functionality I would also appreciate:
Make a row recolor to red if it contains cells that have mismatching data. (such as someone putting their name in someone else's row)
If data is added to a previously empty row, expand the Protected Range by 1 row after 30 minutes.
If a row within a Protected Range becomes empty, the Protected Range automatically sorts itself from A-Z by Column A and reduces its size by 1 row.
Context:
I've recently made a spreadsheet on Google Sheets for my guild in an MMO to track what professions and recipes everyone has, people with the link can perform edits on the sheet, but I do have protected ranges that cover older entries which have their editor access restricted to a small team so random people don't just delete all the data. None of the other officers that regularly maintain the spreadsheets we use have much experience with spreadsheets, which are pretty basic with little automation. It takes three to four of them to do my job when I'm on vacation despite teaching each of them how to maintain the spreadsheets. More automation would be nice for when I go on vacation and eventually retire from that MMO.
This is my first post on this site, I don't know computer programming, not that well-versed with spreadsheets, and trying to google this didn't help since everything I found talked about conditional formatting based on the columns, not the rows.
For now my temporary work-around is to manually add conditional formatting to a range each time I see a row has filled up to change the fill color to green if the cell contains exactly that person's name. Based on prior experience with my guild's other spreadsheets, I know the other officers would not do this themselves.
I'm not sure where to look for help with Google Sheets, but I have a family member that is a developer and I vaguely remember him mentioning this site which is why I'm giving it a shot.
try:
=SUMPRODUCT($A2:$K2<>"")=11
on range A2:K
update:
=(SUMPRODUCT($A2:$R2=$A2)=18)*(A2<>"")
on range A2:R

How can I add an icon in a label?

I have 2 questions need your help.
I would like to add a button on each plot to be a setting button. I use label with event listener and it works well ( as shown in attached file). However, my client asked me to change from normal text to graphic icon? How should I proceed?
As you can see from the attached image, the third plot is macd series. The value rage is from -3e-8 to 3e-8 (by my observation). I manually set the maximum and minimum, and it get incorrect scale as shown.
How should I set the maximum and minimum for yScale?
I don't know how to get maximum and minimum value from a series. Can you suggest me?
A1 – Unfortunately, the current version of AnyChart doesn't provide an opportunity to add custom-made buttons inside the chart. But you can use a trick and use stage based layout. It means that the container includes a stage. The stage includes the stock chart all other elements by layers. Using this approach you can place an image (icon) upon the plot and set a listener just as for the 'settings' label.
For details, please, check the sample in the comment below.
A2 - We are planning to fix this behavior in 8.4.2 update (approximately by the end of November 2018).
I will notify you when the fix becomes available.
As a temporary workaround, you can get min /max value from your MACD indicator. For details, please, check the sample in the comment below.
You can apply min/max to the yScale of plot #0 like this:
chart.plot(0).yScale().minimum(minValue);
chart.plot(0).yScale().maximum(maxValue);
We are glad to inform you that we have released 8.4.2 update which brings many fixes and improvements. This update also includes a fix on the issue you reported. Now calculation of min/max of Y-scale works properly with small values. Update your binaries to get the fix.

DC.js Line Chart - no line being displayed

Need to display line in a line-chart , with the ability to move the tiles, to see a max bitrate value line, to see labels and axis pointers on hover, grouped with a table and time Slider.Y dimension needs to display "bitrate total" or "bitrate Avg" (as defined in code). X dimension needs to display 15 min interval in scope of weeks.
I can upload my data into a table but not into the line graph. I can see points on the graph using .renderDataPoints() but no lines.
I checked the data - could not find any null/NaN values being returned, not using any old version of colors.
The code can be found in https://jsfiddle.net/dani2011/bu2ag0f7/8/. Tried to replace my CSV with var data but nothing is being displayed at the moment in the fiddle. The code as whole is displayed in https://groups.google.com/forum/#!topic/dc-js-user-group/MEslyF2RWRI
Any help would be greatly appreciated.
Here's my go-to-answer for how to put data into a jsFiddle. Basically it's easiest to stick it in an unused tag in the HTML. bl.ocks.org / blockbuilder.org is easier for this.
Here's a fork of your fiddle with the data loaded that way:
http://jsfiddle.net/gordonwoodhull/bu2ag0f7/17/
I also had to remove the spaces from the column names, because those got d3.csv confused and caused the BITRATE calculations to fail.
There was also some stray code inside the renderlet which was failing with a complaint about dim not existing.
The main reason why data was not displaying was because the input groups were not producing usable aggregated data. Your data is very close together in time, so aggregating by week would aggregate everything.
The way to debug this is to put a breakpoint or a console.log before the chart initialization and look at the results of group.all()
In this case bitrateWeekMinIntervalGroupMove and minIntervalWeekBitrateGroup were returning an array with one key/value pair. No lines can be drawn with one point. :)
It looks like you originally wanted to aggregate by 15 minute intervals, so let's get that working.
For whatever reason, there are two levels of aggregation in crossfilter, the dimension level and the group level. The dimension will have first crack at generating a key, and then the group will further refine these keys.
Your min15 function will map each time-key to the 15-minute mark before it, but it needs data that is higher than 15 minutes in resolution. So let's put these groups on the dateDimension, which hasn't already been mapped to a lower resolution:
var minIntervalWeekBitrateGroup = dateDimension.group(min15).reduceSum(function (d) {
return +d.BITRATE
});
var bitrateWeekMinIntervalGroupMove = dateDimension.group(min15).reduce(
...
Great, now there are 30 data points. And it draws lines.
I made the dots a bit smaller :) because at 30 pixels it was hard to see the lines.
Zooming in using the range chart reveals more of lines:
There still seem to be glitches in the reduce function (or somewhere) because the lines drop to zero when you zoom in too far, but hopefully this is enough to get you moving again.
My fork of your fiddle: http://jsfiddle.net/gordonwoodhull/bu2ag0f7/25/

How to update the axis scale on change events in cubism/d3

I am trying to make a demonstration using cubism. I have created a custom context.metric, similar to the random() function on the cubism homepage. This loads my data set and renders correctly, showing a new row each second.
What I want to do now is have the axis scale domain update as well, using the date column from my dataset. For the purposes of demonstration, I want each second that passes in wall-time to correspond to one row in my dataset, which is hourly. I can set the scale domain when I create the context, but I cannot get it to update when new data is fetched.
I have tried to listen for context events such as change, and beforechange and manually update the domain there. It does not seem to work, or I am doing something wrong. Any suggestions would be greatly appreciated.
Thanks for the awesome libraries!
The context's time domain is fixed by the context step and size. For example, if you have a step of ten seconds and a size of 1,440, then the domain is the last four hours. If you use context.axis to display the axis, it will update automatically whenever the context fires a change event; you don't have to do anything. Cubism is designed for realtime dashboards, so it doesn't support advancing an hour per second.

Plotting several jpeg images in a single display

I need to plot and display several jpeg images in a single combined display (or canvas?). For example, suppose I have images {a,b,c,d}.jpg, each of different size, and I would like to plot them on one page in a 2x2 grid. It would be also nice to be able to set a title for each subplot.
I've been thoroughly looking for a solution, but couldn't find out how to do it, so any ideas would really help. I would preferably use a solution that is based on the EBImage package.
There are two ways how to arrange several plots with base graph functions, namely par(mfrow=c(rows,columns)) (substitute rows and columns with integers) and layout(mat) where mat is a matrix like matrix(c(1,2,3,4)).
For further info see ?par, ?layout, and especially Quick-R: Combining Plots.
However, as your question is about images I don't know if it helps you at all. If not, I am sorry for misinterpreting your question.
To add to Henriks solution, a rather convenient way of using the par() function is:
jpeg(filename="somefile.jpg")
op <- par(mfrow=c(2,2)
#plot the plots you want
par(op)
dev.off()
This way, you put the parameters back to the old state after you ran the code. Be aware of the fact this is NOT true if one of the plots gave an error.
Be aware of the fact that R always put the plots in the same order. Using mfrow fills the grid row by row. If you use mfcol instead of mfrow in the code, you fill up column by column.
Layout is a whole different story. Here you can define in which order the plots have to be placed. So layout(matrix(1:4,nrow=2) does the same as par(mfcol=c(2,2)). But layout(matrix(c(1,4,3,2),ncol=2)) places the first plot lefttop, the next one rightbottom, the third one righttop, and the last one leftbottom.
Every plot is completely independent, so the titles you specify using the option main are printed as well. If you want to have more flexibility, you should take a look at lattice plots.
If you do not want the images in a regular grid (the different sizes could imply this), then you might consider using the subplot function from the TeachingDemos package. The last example in the help page shows using an image as a plotting character, just modify to use your different images and sizes/locations.
The ms.image function (same package) used with my.symbols is another possibility.

Resources