Stacked bar chart overwhelmed by one value - flot

I'm using JQuery Flot with the stacking plugin to create a stacked bar chart of revenue over time from a number of different sources. The problem I'm running into is that there is one timepoint where one source gained revenue a couple of orders of magnitude larger than any other in the entire chart.
The end result is that this value dominates the graph, shrinking all the other bars to an unusable height. I can set a max height on the graph, but then you lose being able to visualize the outstanding value.
Is there any best practice in data visualization to address a situation like this? Some flot option/plugin that could help? Or a library that would handle the situation in a way better than flot?

I'm not certain about financial plots, but in scientific plotting, to emphasize data closer to 0, a logarithmic scaled axis is frequently used. Unlike a linear scaled axis where each equally spaced tick represents a +N, in a log scaled axis each equally spaced tick represents an order of magnitude increase. The simplest case is an exponential increase where the axis goes 0.1, 1, 10, 100, 1000, etc...
For instance here's the same bar graph with a linear and log scaled axis:
Here's the flot code I used to generate this (fiddle here):
$(function() {
var series = {data: [[0, 0.1], [1, 1], [2, 10], [3, 100000]],
lines: {show: false},
bars: {show: true}}
$.plot("#linear", [ series ]);
$.plot("#log", [ series ], {
yaxis: {
min: 0.1,
max: 150000,
ticks: [[0.1,"0.1"], 1, 10, 100, 1000, 10000],
transform: function (v) {
return (v == 0) ? Math.log(0.0001) : Math.log(v);
},
inverseTransform: function (v) {
return Math.exp(v);
}
}
});
});

Related

How to get new coordinates after rotation in 3D at certain angle in terms of trigonometry, Just like given example in codesandbox

I need your help.
I know about rotation matrix and how it is used to get the new coordinates after rotating in certain angle. But I am not able to get how in below code new coordinates are being captured and cube is revolving around the imaginary circle.
I am using react three fiber - react library for using ThreeJS. If you don't know about this library, still you can figure it out if you are good in computer graphics and mathematics of it.
Live example - https://codesandbox.io/s/capra-christmas-forked-eukvyi
function Box() {
const [ref, api] = useBox(() => ({ mass: 1, args: [1, 1, 1], position: [1, 1, 1], isKinematic: true }))
useFrame((state) => {
const t = state.clock.getElapsedTime() // get elapsed time within frame. if you new to react three fiber you can think it will get new increasing time after every sec.
api.position.set(Math.cos(2 * t ) * 10, Math.sin(20 ) * 5, Math.sin(20) + 1.5) // how this line of code specifying coordinates (x,y,z) in terms of trigonometry
api.rotation.set(Math.sin(t * 6), Math.cos(t * 6), Math.sin(t * 6))
})
return (
<mesh ref={ref} castShadow receiveShadow position={[10, 0, 0]}>
<boxBufferGeometry attach="geometry" args={[1, 1, 1]} />
<meshLambertMaterial attach="material" color="red" side={THREE.DoubleSide} />
</mesh>
)
}
in the code sandbox you referenced they are using the parametric equation of a circle to rotate an object around a given point, heres a nice visualization.
https://www.mathopenref.com/coordparamcircle.html
the idea is to change one axis based on cos(theta) and another based on sin(theta) *theta in this case being time
api.position.set(Math.cos(2 * t) * 10, Math.sin(20 * t) * 5, Math.sin(20) + 1.5)
it looks like in your code you are changing your cos function based on time but not your sin function. try using the snippet above. also the third axis in the code sandbox is just used to make the object move up and down a little as it rotates. You can look into the maths in the link above to get a better understanding of what is happening.

Is it possible for force a square grid in Flot?

I have a "real space" plot where I'm visualizing planetary orbits. I would like to force square x- and y-ticks such that I'm looking at a square grid on which the orbits are plotted. I've tried setting ticks, tickSize, and minTickSize all to 1 in the options, but this didn't work. (Note that the tick size doesn't necessarily have to be 1.) In flot chart ticks lines not uniform, there is someone trying to do something similar, but this seems to be pretty specific to EKG charts. Alternatively, is it possible to turn off auto-scaling? I wonder if this would accomplish what I'm after.
When your chart is square and has the same min-/max-values for both axes you get a square grid automatically. No need to set any of the tick options. See this example fiddle.
var options = {
xaxis: {
min: 0,
max: 10
},
yaxis: {
min: 0,
max: 10
}
};

geoxml3: Syntax for markerOptions{shape}

I want to limit the clickable area of all the icons from a KML file, and I'm a little stumped about how to make that happen. The icons are all the same typical-style pointer, and I'd like to limit the clickable area to the circle encompassed by the top of the pointer. The icon is 19x32, so I think I want a circle centered 9px from the top, 9px from the left, with a radius of 9px. If geoxml3 will do that, I figure that would be specified in the parser object, though maybe it would be in the IconStyle in the KML file. If in fact that would be in the parser object I haven't found the right syntax. It is apparently not:
var blues = new geoXML3.parser({map: map, singleInfoWindow: true, zoom: false, markerOptions: {shape: {type:circle, coords: [9px,9px,9px]}}});
blues.parse('allbluesdance.kml');
The markerOptions option to GeoXml3 is exactly a Google Maps Javascript API v3 markerOptions object.
Your icon is 49x32 pixels, the center of the circle is defined from the top left, so you probably want 24,9 for the center and a radius of 9:
var blues = new geoXML3.parser({
map: map,
singleInfoWindow: true,
suppressDirections: true,
markerOptions: {
shape: {
type: 'circle',
coords: [24,9,9]
}
},
zoom: false
});
From the documentation on Complex Icons:
// Shapes define the clickable region of the icon.
// The type defines an HTML <area> element 'poly' which
// traces out a polygon as a series of X,Y points. The final
// coordinate closes the poly by connecting to the first
// coordinate.
var shape = {
coords: [1, 1, 1, 20, 18, 20, 18 , 1],
type: 'poly'
};
The HTML area circle shape, looks like what you have should work if you remove the "px" (the documentation says an array of numbers), except that it is off to the left of the icon.
working example

jquery flot bar chart bar width

I'm using jquery flot library to plot a bar chart. The bars in my chart are consistantly too thin, about 2px in width. But when I set
lineWidth: 15
the bars become the width I want, but the first and the last bars spill over the graph border. I found a simple test flot bar chart with a limited number of points, which looks fine when implemented locally. My conclusion is that maybe I have way too much data, and so the bars are thin in contrast to the amount of points. But I'm hoping there is a way to get the bars to be wider some other way and for them not to spill over the graph border.
Any suggestions are much appreciated. Here is what I have:
$.plot(this.get('datasets'), {
bars: {
show: true,
align: "center",
fill: true,
//lineWidth: 15
},
xaxis: {
mode: "time", //"categories",
timezone: "browser",
tickLength: 0
}
});
You're using lineWidth instead of barWidth. So your bars are the same width; they just look thicker (and spill over the border) because the lines around them are thick.
The reason why your bars are so narrow are because the width is expressed in axis units, not pixels. In your case, where you're using a time-mode axis, the bar width will be quite large. If you want a bar to cover one hour, then your barWidth should be 60 * 60 * 1000 = 3600000.

Find the coordinates of the Frame/Axes in the final display area of a plot

If I do a Plot with Frame->True is there a way I can find the coordinates of the corners of the Frame in the absolute coordinates of the image? I have the numerical values of PlotRange and PlotRangePadding but note that I don't want to tamper with the actual plot in any way, just find out where in the full display area Mathematica chooses to place the frame/axes of the plot.
As pointed out by Brett Champion, I'm looking for the coordinates {x,y} such that Scaled[{0,0}] == ImageScaled[{x,y}].
[Note that I edited this question to remove my confusing misuse of the term "scaled coordinates".]
The corners of the frame are at Scaled[{0,0}] and Scaled[{1,1}].
The corners of the full graphic (including labels) are at ImageScaled[{0,0}] and ImageScaled[{1,1}].
Converting between them is hard, although in theory it's possible to convert Scaled and user (unscaled) coordinates if you know the actual, numeric, settings for PlotRange and PlotRangePadding.
Depending on your application, you might also be able to use MousePosition, which knows these things as well.
Rasterize (and HTML export) also know how to find bounding boxes of annotations, in a bitmap/pixel coordinate system:
In[33]:= Rasterize[
Plot[Sin[x], {x, 0, 10}, Frame -> True,
Prolog -> {LightYellow,
Annotation[Rectangle[Scaled[{0, 0}], Scaled[{1, 1}]], "One",
"Region"]}], "Regions"]
Out[33]= {{"One", "Region"} -> {{22., 1.33573}, {358.9, 209.551}}}
Here's how dreeves used that Rasterize trick to make a function to return exactly what he was looking for (note the assumption of a global variable imgsz which gives the ImageSize option for rasterizing the plot -- the coordinates of the frame depend on that value):
(* Returns the geometry of the frame of the plot:
{width, height, x offset, y offset, total width, total height}. *)
geom[p_Graphics] := Module[{q, x1, y1, x2, y2, xmax, ymax},
q = Show[p, Prolog->{Annotation[Rectangle[Scaled[{0,0}], Scaled[{1,1}]],
"MAGIC00","MAGIC11"]}];
{{x1,y1}, {x2,y2}} = Rasterize[q, "Regions", ImageSize->imgsz][[1,2]];
{xmax,ymax} = Rasterize[p, "RasterSize", ImageSize->imgsz];
{x2-x1, y2-y1, x1, y1, xmax, ymax}]
The coordinates of the upper left corner of the frame are always Scaled[{0,1}].
The coordinates of the lower right corner of the frame are always Scaled[{1,0}].
Let's place large points at the upper left and lower right corners:
Plot[Cos[x], {x, 0, 10}, Frame -> True,
Epilog -> {PointSize[.08], Point[Scaled[{0, 1}]], Point[Scaled[{1, 0}]]} ]
When I click on the graph (see below) , it is obvious that there is no padding around the frame of the plot.
Now, with ImagePadding on, let's place Points in the same corners:
Plot[Cos[x], {x, 0, 10}, Frame -> True,
ImagePadding -> {{37, 15}, {20, 48}},
Epilog -> {PointSize[.08], Point[Scaled[{0, 1}]], Point[Scaled[{1, 0}]]} ]
The Points stay at the corners of the graph frame.
There is ImagePadding around the graph frame.
EDIT: Based on the clarification of the question by dreeves.
Plot[Cos[x], {x, 1, 9}, ImageSize -> 300, AspectRatio -> 1,
Frame -> True, ImagePadding -> 30,
FrameTicks -> {Range[9], Automatic},
Epilog -> {PointSize[.08], Point[Scaled[{0, 1}]], Point[Scaled[{1, 0}]]}]
I've drawn the plot as 300x300 to simplify the numbers.
Here's the analysis.
Documentation states that ImagePadding "is defined within ImageSize".
The image shown above has a width and height of 300 pixels.
There is a 30 pixel margin drawn around the frame; this corresponds to 10% of the width and height.
So the frame corners should be, starting from the origin, at ImageScaled[{.1,.1}], ImageScaled[{.9,.1}, ImageScaled[{.9,.9}] & ImageScaled[{.1,.9}].
It's easy to work out the value for other AspectRatios and ImageSizes.
One possibility is to take manual control of ImagePadding:
Plot[Sin[x], {x, 0, 10}, Frame -> True,
ImagePadding -> {{30, 5}, {20, 5}}]
ImageTake[Rasterize[%], {5, -20}, {30, -5}]

Resources