How to chart d3 venn diagram with two distinct sets? - d3.js

I'm trying to draw venn diagram in d3 from the post as below.
http://bl.ocks.org/bessiec/986e971203b4b8ddc56d3d165599f9d0
I used the data as below.
var sets =[
{sets:["students"], figure: 600, label: "students", size: 600},
{sets:["pass"], figure: 455, label: "pass", size: 455},
{sets:["students","pass"], figure: 455, label: "", size: 455},
{sets:["students","fail"], figure: 145, label: "", size: 145},
{sets:["pass","fail"], figure: 0, label: "", size: 0},
{sets:["fail"], figure: 145, label: "fail", size: 145},
];
I want that students pass + fail must get into the students, how to shall i do that with the above library.
There are 600 students, of which 455 passed and 145 failed. then the two circles must be in students. How shall i achieve it using the above library, if not is there any d3 library to draw venn diagrams of such sceanarios.

Related

How do I generate an A4-sized single card in squib?

I'm trying to use Squib to generate a map for a boardgame by printing one "card" which is the size of an entire A4 sheet of paper.
There must be some default in Squib that is cropping the resulting images and text, however, so that only a portion of it is visible.
Here is some sample code demonstrating the problem:
require 'squib'
Squib::Deck.new cards: 1, layout: [] do
rect x: 0, y: 0, width: 3457, height: 2438, fill_color: 'BLUE'
circle x: 1728, y: 1218 , radius: 1218, fill_color: 'RED'
save_pdf file: 'maps_1.pdf'
end
At 300 dpi, a landscape A4 piece of paper should be 3457x2438 pixels, so this ought to display a blue box with a red circle, filling the page. Instead it displays a poker-card-sized chunk of that image in the upper left hand corner:
resulting pdf
The result is much the same if I use millimeters, with a sprue:
require 'squib'
Squib::Deck.new cards: 1, layout: [] do
rect x: 0, y: 0, width: '295mm', height: '208mm', fill_color: 'BLUE'
circle x: '147.5mm', y: '104mm' , radius: '104mm', fill_color: 'RED'
save_pdf file: 'maps_1.pdf', sprue: 'layouts/map-sprue.yml'
end
Sprue:
---
sheet_width: 297mm
sheet_height: 210mm
card_width: 295.0mm
card_height: 208.0mm
cards:
- x: 0.0mm
y: 0.0mm
crop_line:
lines:
- type: :vertical
position: 0.0mm
- type: :vertical
position: 295.0mm
- type: :horizontal
position: 0.0mm
- type: :horizontal
position: 208.0mm
Does anyone know what is forcing squib only to address a portion of the A4 page?
thanks
You want width and height as parameters to Squib::Deck.new
To make your "card" the entire size of an A4 page, use something like this:
Squib::Deck.new(width: '210mm', height: '297mm') do
end
HOWEVER If you are planning on printing to an A4 page I recommend making it a tad smaller so that your printer doesn't autoscale or cut things off. My printer does fine with 6mm margin, probably something like 200x290.
You probably don't need sprues in this situation.

Recharts value at pointer to show in tooltip?

Is it possible in Recharts to show a Horizontal line at the Y location where the user has their mouse over and retrieve that Y value so we can display it on the Tooltip?
https://meridian.a2z.com/components/tooltip/?platform=react-web
I've been trying to do some research into how we could get the Y value on the graph where the mouse is hovering or clicked, but I'm having trouble seeing where we could even pull that out.
Any tips on attributes or components we could use to grab this data? Is it even something we have access to from the library?
To clarify, we're trying to get the value of the Y axis at where the user has their cursor over the graph.
So if the graph looks like this and the user has their mouse at the pink dot location, I would be trying to grab out the value of ~7000 - what the y value would be at that graph location
Edit:
Note about responsiveness:
If you want to make this responsive, just adjust the chartBounds based on the padding/margin you've applied to the chart component and you should be good to go.
If you're trying something more advanced and need the height and width to pass to the chart component for more calculations, the following article should help: https://www.pluralsight.com/tech-blog/getting-size-and-position-of-an-element-in-react/
NOTE: This is a bit of a hack and may not be a perfect solution but it should be enough to get you on the right track
You should be able to use the chartX and chartY fields from onMouseMove. Unfortunately, this is just the pixel value under the cursor but you should be able to translate it into the range you are using for your graph.
Here is an example put together using the SimpleLineChart example recharts has up. This should work if you just want to get the Y value under the user's cursor and can be extended to get the X value as well.
const {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend} = Recharts;
const data = [
{name: 'Page A', uv: 4000, pv: 2400, amt: 2400},
{name: 'Page B', uv: 3000, pv: 1398, amt: 2210},
{name: 'Page C', uv: 2000, pv: 9800, amt: 2290},
{name: 'Page D', uv: 2780, pv: 3908, amt: 2000},
{name: 'Page E', uv: 1890, pv: 4800, amt: 2181},
{name: 'Page F', uv: 2390, pv: 3800, amt: 2500},
{name: 'Page G', uv: 3490, pv: 4300, amt: 2100},
];
//The pixel bounds for the LineChart, 0,0 is the top left corner
// these were found using the inspector built into the web browser
// these are in pixels but correspond to the values used in your graph
// so 246 is 0 Y on the graph and 5 is 10000 Y on the graph (according to your data)
const chartBoundsY = {min: 246, max: 5}
// The bounds we are using for the chart
const chartMinMaxY = {min: 0, max: 10000}
// Convert the pixel value from the cursor to the scale used in the chart
const remapRange = value => {
let fromAbs = value - chartBoundsY.min
let fromMaxAbs = chartBoundsY.max - chartBoundsY.min
let normal = fromAbs / fromMaxAbs
let toMaxAbs = chartMinMaxY.max - chartMinMaxY.min
let toAbs = toMaxAbs * normal
return Math.ceil(toAbs + chartMinMaxY.min)
}
const SimpleLineChart = React.createClass({
render () {
return (
<LineChart
width={600} height={300} data={data}
margin={{top: 5, right: 30, left: 20, bottom: 5}}
onMouseMove={props => {
// We get the values passed into the onMouseMove event
if(props.isTooltipActive) {
// If the tooltip is active then we display the Y value
// under the mouse using our custom mapping
console.log(remapRange(props.chartY))
}
}}
>
<XAxis dataKey="name"/>
<YAxis/>
<CartesianGrid strokeDasharray="3 3"/>
<Tooltip/>
<Legend />
<Line type="monotone" dataKey="pv" stroke="#8884d8" activeDot={{r: 8}}/>
<Line type="monotone" dataKey="uv" stroke="#82ca9d" />
</LineChart>
)
}
})
ReactDOM.render(
<SimpleLineChart />,
document.getElementById('container')
)
You can open this example in jsfiddle and paste in the code above in the JS editor to try it out for yourself. http://recharts.org/en-US/examples
Here is the documentation for the mouse event for the LineChart: http://recharts.org/en-US/api/LineChart
This can be done with the axis scale option together with d3's invert method.
The following code excerpt should give you an idea.
const domainY = d3.extent(data, d => d[keyY])
const scaleY = d3.scaleLinear().domain(domainY).range([0, 1])
<AreaChart
onMouseDown={(e) => console.log(scaleY.invert(e.chartY))}
...
<YAxis
domain={['auto', 'auto']}
dataKey={keyY}
type="number"
scale={scaleY}
...

Query a Chart with C3.js

I created a simple pie chart with around 10 items (using C3.js and D3.js). Now, in a second visualization (a table) I want to know the colors of each of the items, to also represent them in the table.
Is it possible to query the chart to receive the item's name and color?
I know I can manually hardcode colors for items and just use the same colors. However, this is not applicable in my case, as the items in the pie chart vary greatly (and I don't know them yet, as it is dependent on the user), hence my question.
Quick look at the source code reveals that you are correct, it's a category10().
Further it retrieves them by a key of "data id", which appears to be the first "column" in it's data input format:
columns: [
['data1', 30, 200, 100, 400, 150, 250], //<-- data1 is id
['data2', 130, 340, 200, 500, 250, 350]
]
You can inspect which are used by:
> chart.internal.color('data1')
"#1f77b4"
> chart.internal.color('data2')
"#ff7f0e"

jqPlot MeterGaugeRenderer - set diameter causes error

I am showing multiple Meter Gauges on a single page, in conjunction with Bootstrap, to provide responsiveness. What is obvious is they are all calculating slightly different sizes, so I hoped to use diameter.
Here is my working code:
s1 = [322];
$.jqplot('spend',[s1],{
seriesDefaults: {
renderer: $.jqplot.MeterGaugeRenderer,
rendererOptions: {
min: 100,
max: 500,
intervals:[200, 300, 400, 500],
intervalColors:['#66cc66', '#93b75f', '#E7E658', '#cc6666'],
intervalOuterRadius: 56,
ringColor: '#222',
padding: 3,
tickColor: '#111',
ringWidth: 4,
needleThickness: 11,
shadowOffset: 10,
label: "£"
}
},
title: 'Spend'
});
If I add
diameter:200,
I get no output, and:
'this._center.0' is null or not an object jqplot.meterGaugeRenderer.js, line 616 character 13
'this._center.0' is null or not an object jqplot.meterGaugeRenderer.js, line 616 character 13
I have also tried
diameter:50,
and
diameter:500,
in case I was not providing adequate space, or too much space, but I rather doubt it, as intervalOuterRadius is set at 56, I have also assumed that
diameter:200
is correct syntax given that
intervalOuterRadius:56
(as well as various other values) is correct. I cannot find anyone else who has had this problem, and have had no response on the jqplot google group.
Oh yeah, and I'm primarily writing for IE8 atm but it will need to be used on ie11 in time.

Discrete filter for D3 Crossfilter Dimensions

Is there a way to create a dimension on a attribute that has one or more values? For example
{quantity: 2, total: 190, tip: 100, items: ["apple","sandwich"],
{quantity: 2, total: 190, tip: 100, items: ["ice-cream"]},
{quantity: 1, total: 300, tip: 200, items: ["apple", "coffee"]}
My goal is to create a cross filter that can filter out entries along a dimension that has ordinal values. Is there a way I write a filter/dimension that will allow me to say "I want all entries that have the item 'apple'"?
The only workaround i can think of is to create a dimension for each item. Like so:
var paymentsByApple = payments.dimension(function(d) { return $.inArray("apple", d.items); });
var paymentsByCoffee = payments.dimension(function(d) { return $.inArray("coffee", d.items); });
// and one for every possible item
The main problem is that I don't want to enumerate and hard code all the different objects. Moreover, I may end up having lots of possible different items. Is there a smarter way to do this?
Thanks in advance!
Facing the same problem here and don't see an easy workaround with the current lib features, see this.
The problem with changing the datamodel to fit a single value dimension as proposed by Pablo Navaro is that you need to make sure that the stats calculated for other dimensions are not distorted (double counting, correcting means, ....)
Hope to see a filter working on multiple value dimension, or to have some more time to dig into the codebase to propose one ...
What about changing your data model? I think that using:
[{id: 1, quantity: 1, total: 100, tip: 50, item: "apple"},
{id: 1, quantity: 1, total: 90, tip: 50, item: "sandwich"},
{id: 2, quantity: 1, total: 190, tip: 100, item: "ice-cream"},
{id: 3, quantity: 1, total: 300, tip: 100, item: "apple"},
{id: 3, quantity: 1, total: 300, tip: 100, item: "coffee"}]
Maybe you can compute the totals by id using reduceSum

Resources