How do I make dynamic bar colours in KDB with KX Developer? - kdb

t: ([] x: til 4; y: -2 3 -4 5)
fillfn: {?[y > 0;`green;`red]}
.qp.go[1000;500] .qp.bar[t; `x; `y] .qp.s.geom[``fill`sortByValue!(::; fillfn; 0b)]
x y
----
0 -2
1 3
2 -4
3 5
Two questions:
How do I fix the bars starting at the bottom instead of zero?
How do I set the fill to be a green bar for positive and a red bar for negative y?

The solution to this turns out to be a different function altogether.
One needs to use a .qp.interval chart, setting one coordinate to be zero always.
For me, this looked like:
plot: { .qp.go[1500;500] .qp.interval[x; `t; `y; `r] .qp.s.aes[`fill; `pos], .qp.s.scale[`fill; .gg.scale.colour.cat 01b!(`red; `green)]}
where y is a column of zeroes.

Related

Conditional formatting in Tableau connected to Cube data

Could someone help me to color these measures on 3 variations - less than 0, equal to 0 and greater than 0. I tried with a calculation
IF [Margin 1] > 0 THEN 1 ELSEIF [Margin 1] < 0 THEN 2 ELSEIF [Margin 1] = 0 THEN 3 END
The reason I have assigned numbers instead of string in the above calculation is, the data is from a cube which will not allow string to be mixed with IF conditon
This is only for Margin 1 while a similar one is also required for Margin 2 and Margin 3 as well. Once I put this calculation to color shelf it colored first value of Margin 1 correctly but at the same time even colors Margin 2 and Margin 3 as well with same shade.
Could someone help to nest color logic calculation for all three Margins so I can have control to choose less than, equal to and greater than 0 in different shades.
Attached is the image of data and tableau sheet of what I have arrived as of now, do let me know for any other details
Not sure how the fact the data is from cube makes much difference, inside of tableau you're looking at a integer and returning a string shouldn't matter.
If you want give this a try
create a calculated field like this:
ZN([Margin 1]) + ZN([Margin 2]) + ZN([Margin 3])
Then create your if statement based on the new calculated field returning string
If [NewCalculated field] <0 then
"Red"
If [NewCalculated field] 0 then
"Amber"
Else
"Green"
End
Have a go

superimpose marker on barplot

I create a figure using a barplot that represents means of groups.
I have a matrix that tells me whether the means are statistically different.
sign_diff =
0 0 0 1
0 0 0 1
0 0 0 0
1 1 0 0
In this case the means of the first group and second group are significantly different from the mean of the 4th group.
How to read the matrix:
first rows: there is a 1 in the last column -> first bar is different from bar 4 so bar 1 and bar 4 get a star.
second row: there is a 1 in the last column -> second bar is different from bar 4 so bar 2 and bar 4 get a star. In more since bar 1 and bar 2 are not different between them the stars in bar 1 and bar 2 should be at the same high
How can I add a marker on top of the bars that are different?
I would like to have something like this:
Please note that the first two stars should be at the same levels indicating that bar1 and bar2 do not differ, but they both differ from bar4 (then the star on top of bar 4 should be higher)
Hope you can help me
I'm still not sure I quite grasp the height logic (and we don't have a functioning example) but in the meantime there's a simple answer the superimposition question. You can use line to superimpose the stars onto your plot.
For example:
y = [1 2 3 4];
bar(y);
ylim([0 6]);
sign_diff = [0 0 0 1; 0 0 0 1; 0 0 0 0; 1 1 0 0];
needs_star = (sum(sign_diff) ~= 0); % See which bars need a star
star_heights = sum(sign_diff).*0.75;
star_x = 1:length(y);
star_y = max(y) + star_heights;
star_x = star_x(needs_star);
star_y = star_y(needs_star);
line(star_x, star_y, ...
'linestyle', 'none', ...
'marker', 'p', ...
'markersize', 15 ...
);
Produces the following:
line accepts XY inputs, so if you can create coordinates for your stars based on your sign_diff matrix you can use them in the line call.
Edit: I have updated with my stab at figuring out the logic. Some tweaks will be needed based on your data. The ylim and max calls will need to be adjusted based on the maximum height of the data in your graph in order to fit everything into the axes and to make sure there is no overlap. You can tweak the 0.75 value to whatever you would like in order to show the differences adequately. This is probably not the most efficient method but the behavior is at least explicit.

How to add label or change the colour of certain bar in multiple bar plot

Lets say I have a multiple bar, which looks smth like that:
aa = repmat([1 2 10 5 15 3], 5,1)
aa =
1 2 10 5 15 3
1 2 10 5 15 3
1 2 10 5 15 3
1 2 10 5 15 3
1 2 10 5 15 3
bar(aa)
What I need is to put a star or a label on some certain column, which sutisfies some conditions. Another option is to change the colour of that bar.
If I could get the coordinates of each column I could use plot. Or maybe I can modify errorbar somehow?
Thanks for any advices.
Problem
You can get the x and y values of the bars (x=horizontal position, y=height of each bar) using:
hb=bar(aa);
x=cell2mat(get(hb,'Xdata'));
y=cell2mat(get(hb,'Ydata'));
which you can then use to plot a textlabel with text,
or even just plot the mark symbols with plot:
plot(x,y,'*',Markersize',12)
Unfortunately, this only works correctly if you only have one single serie of data, because Xdata contains the index in the series (1,2,3,etc). For multiple series matlab spreads the bars around that index, but the Xdata values are all the same (despite in the plot, they aren't plotted at exact the same position).
Solution
Add the option 'hist' to the bar plotting:
hb=bar(aa,'hist')
this creates patches rather than barseries, and
x=cell2mat(get(hb,'Xdata'));
y=cell2mat(get(hb,'Ydata'));
now contains the (actual) corners of those patches. Extract the x-center as follows:
xcenter = 0.5*(x(2:4:end,:)+x(3:4:end,:));
The height is obtainable with one of the upper corners of the patch:
ytop = y(2:4:end,:);
Now you can use that for the plotting:
idx_mark = 3;
plot(xcenter(idx_mark ,:),ytop(idx_mark ,:),'*','Markersize',12)
or for annotation:
text(xcenter(idx_mark ,2),ytop(idx_mark ,2),'MARKED',...
'HorizontalAlignment','center', ...
'VerticalAlignment','bottom' )
I think that what you could do that (for the colors) with playing a little with the bar function properties.
It also all depends if you know more or less how your plot will look like; if you know beforehand I think you could use XTick and XTicklabel to label you columns.
http://www.mathworks.nl/help/techdoc/ref/bar.html

how to plot with vectical lines with gnuplot?

I study for sometime but didn't get the answer yet.
The data is like:
#X0, Y0_0, Y0_1
1 1 2
3 2 4
7 1 3
....
I need to draw vectical line from (X0, Y0_0) to (X0, Y0_1). gnuplot has financebar and candlesticks but they are too much.
I just want a single vectical line for each record.
Appreciate for any help.
If I understand correctly what you are after, the following script should do the job:
set offsets 1, 1, 1, 1
set key off
plot "-" u 1:2:(0):($3) w vectors nohead
1 1 2
3 2 4
7 1 3
e
What it does:
It sets the offset, so that you can see the left and right vector, so that it is not hidden by the axis.
Remove the label, since it has no use in this example
Plots vectors with no head (a single vertical line). The "parameters" are as stated here the x y dx dy. The (0) stands for dx=0 and the brackets are important. Otherwise the column 0 would be used which in gnuplot is the index of the data (line number).
Below the plot you will get with the script above:

How do I get the indexes of specific elements based on value and then replace them in MATLAB?

From the exercises in a book I am using to learn MATLAB:
Given x = [3 15 9 12 -1 0 -12 9 6 1],
provide the command(s) that will
A) set the values of x that are
positive to zero
B) set values that are multiples of 3
to 3 (rem will help here)
C) multiply the values of x that are
even by 5
D) extract the values of x that are
greater than 10 into a vector called
y
E) set the values in x that are less
than the mean to zero
F) set the values in x that are above the mean to their difference from the mean
Question a) will teach you the following elements:
find a function that returns indexes given a condition, in your case x>0
use indexing in order to set selected values in x to 0
to be continued ...
x = [3 15 9 12 -1 0 -12 9 6 1]
vi = (x < 0) % statement that returns a boolean, gives a vector like
% [0 0 0 0 1 0 1 0 0 0]
x(vi) = -x(vi) % does the operation (negating in this case) on the relevant
% values of x (those with a 1 from above)
Without actually doing your homework, they all follow the above pattern.
I agree with the comments to your question, that is not necessarily the right way to go if you really want to learn something.
As to answer your question, MATLAB has a fantastic function browser I strongly suggest you take a look at it. With well chosen keywords you can go a long way. :)