Wireframe plot with small values in R - r

I have data with very small values between -1 to 1 in X, Y and Z values between -1 to 1 like below
X,Y,Z
-0.858301,-1,1.00916
-0.929151,-1,1.0047
-0.896405,-0.940299,1.00396
-0.960967,-0.944075,1.00035
wireframe(Z~X+Y,data=sol)
Seems wireframe works only with larger values (1, 2, 3...) , How do I plot small values?

wireframe might be use in one of two ways -
With a rectangular data matrix where the values of x and y are implied by the shape of the matrix.
wireframe(matrix(rnorm(100),ncol=5),drape=TRUE)
Or with a dataframe, where the values of x and y are explicit, and here you can use a formula for the relationships between the columns.
df<-expand.grid(x = seq(0,.1,.01), y = seq(0,.1,.01))
df$z<-rnorm(121)
wireframe(z~x*y,data=df,drape=TRUE)

I've found that if you include the line defining the z axis limits, then you can't draw it below 1. But if you take out the defined axis limits, and let R graph it itself, then it works and you can graph small numbers.

Related

How to plot data over a non-rectangular region in Octave?

I have three arrays of equal size: x, y, z. I want to plot z over x, y. Problems is, those x and y do not represent a rectangular region, such as what would be in case of using meshgrid function.
I know I can use something like scatter, but that would graphically only give me the points themselves. What I want is the filled, smoothed picture. So as opposed to this created by scatter:
I would like something like this:
Any suggestion how this can be done? I have a feeling the data must be smoothed out somehow via interpolation or something else prior to plotting which itself should be simple.
You can use griddata() to interpolate your x,y data on a regular grid and then you can use imagesc() to plot the result.
Here is a minimal example with a basic circle:
% INPUT
x = cos(0:0.1:2*pi);
y = sin(0:0.1:2*pi);
z = (0:0.1:2*pi);
% Create a regular grid that have the same boundary as your x,y data
[xx,yy] = meshgrid(linspace(-1,1,100),linspace(-1,1,100));
% Grid interpolation
zz = griddata (x, y, z, xx, yy);
% Plot
imagesc(zz)
colormap ([jet(); 1 1 1]); % I add a last [1 1 1] triplet to set the NaN color to white.
Noticed that this will only works if you keep the default interpolation method (which is a linear interpolation). The other method (cubic and nearest) will extend the domain of definition by analytic continuation.
I realized that the best approach would be some slight modification to what obchardon is proposing:
instead of the lines
imagesc(zz)
colormap ([jet(); 1 1 1]);
do this:
surf(xx, yy, zz);
shading interp;
colormap("jet");
This eliminates the problem with the black background. Then all it takes is just to rotate the camera with a mouse so that the 3d surface looked like 2d from above.

3D Ploting in Scilab: Weird plot behaviour

I want to plot a function in scilab in order to find the maximum over a range of numbers:
function y=pr(a,b)
m=1/(1/270000+1/a);
n=1/(1/150000+1/a);
y=5*(b/(n+b)-b/(m+b))
endfunction
x=linspace(10,80000,50)
y=linspace(10,200000,50)
z=feval(x,y,pr)
surf(x,y,z);
disp( max(z))
For these values this is the plot:
It's obvious that increasing the X axis will not increase the maximum but Y axis will.
However from my tests it seems the two axis are mixed up. Increasing the X axis will actually double the max Z value.
For example, this is what happens when I increase the Y axis by a factor of ten (which intuitively should increase the function value):
It seems to increase the other axis (in the sense that z vector is calculated for y,x pair of numbers instead of x,y)!
What am I doing wrong here?
With Scilab's surf you have to use transposed z if comming from feval. It is easy so realize if you use a different number of points in X and Y directions, as surf will complain about the size of the third argument. So in your case, use:
surf(x,y,z')
For more information see the help page of surf.
Stephane's answer is correct, but I thought I'd try to explain better why / what is happening.
From the help surf page (emphasis mine):
X,Y:
two vectors of real numbers, of lengths nx and ny ; or two real matrices of sizes ny x nx: They define the data grid (horizontal coordinates of the grid nodes). All grid cells are quadrangular but not necessarily rectangular. By default, X = 1:size(Z,2) and Y = 1:size(Z,1) are used.
Z:
a real matrix explicitly defining the heights of nodes, of sizes ny x nx.
In other words, think of surf as surf( Col, Row, Z )
From the help feval page (changed notation for convenience):
z=feval(u,v,f):
returns the matrix z such as z(i,j)=f(u(i),v(j))
In other words, in your z output, the i become rows (and therefore u should represent your rows), and j becomes your columns (and therefore v should represent your columns).
Therefore, you can see that you've called feval with the x, y arguments the other way round. In a sense, you should have designed pr so that it should have expected to be called as pr(y,x) instead, so that when passed to feval as feval(y,x,pr), you would end up with an output whose rows increase with y, and columns increase with x.
Then you could have called surf(x, y, z) normally, knowing that x corresponds to columns, and y corresponds to rows.
However, if you don't want to change your whole function just for this, which presumably you don't want to, then you simply have to transpose z in the call to surf, to ensure that you match x to the columns or z' (i.e, the rows of z), and y to the rows of z' (i.e. the columns of z).
Having said all that, it would probably be much better to make your function vectorized, and just use the surf(x, y, pr) syntax directly.

Data file format for 3d plots in Octave

I have file(s) containing N X values and M Y values. Also one containing Z at each value of (X,Y). So N rows and M columns.
I did this:
a=load('z.txt')
surf(a)
which plots Z ok but the axes are just the datapoint number. How do I get the axes to match the X and Y data?
This seems to do the trick:
x=load('x.txt')
y=load('y.txt')
z=load('z.txt')
surf(x,y,z)
Although there are probably more elegant ways.

R code: calls to rnorm for x, y axes in plotting hierarchical clusters

This is a random data set being generated here for understanding and plotting a hierarchical cluster in R. I need to know the logic behind why the difference in the calls to rnorm for the x and y axis of the plot. Why y<-rnorm(12, mean=rep(c(1,2,1) when I would have expected mean=rep(c(1,2,3). Perhaps just the literal translation would help me.
set.seed(1234); par(mar=c(0,0,0,0)) ## par sets parameter mar (sets margin)
x<-rnorm(12, mean=rep(1:3,each=4),sd=0.2) ## repeat the vector 3 times
y<-rnorm(12, mean=rep(c(1,2,1),each=4),sd=0.2) ## ?????
plot(x,y,col="blue",pch=19,cex=2)
text(x+0.05,y+0.05,label=as.character(1:12))
Any help appreciated!
If you run your code, you get graphical output that looks something like this:
You can see that there are three clusters at three distinct mean x values (1, 2 and 3) but only two distinct y values (1 and 2, then 1 again). That's because the code for the y values has mean=rep(c(1,2,1),each=4). i.e. the rnorm function is generating twelve random y values, the first four of which have a mean of 1, the second four of which have a mean of 2 and the third four of which have a mean of 1.

All points on Line

If I draw a line from let's say: (2,3) to (42,28), how can I get all points on the line in a Point list? I tried using the slope, but I can't seem to get the hang of it.
To be clear: I would like all the pixels that the line covers. So I can make the line 'clickable'.
This is a math question. The equation of a line is:
y = mx + c
So you need to figure out the gradient (m) and the intercept (c) and then plug in values for x to get values for y.
But what do you mean by "all the points on a line"? There is an infinite number of points if x and y are real numbers.
You can use the formula (x-x1)/(x1-x2) = (y-y1)/(y1-y2). And you know the points with x values ranging from 2 to 42 are on the line and their associated y values have to be found. If any of the resulting y value is not an integer then it should be approximated rightly. And if two consecutive y values differ by more than 1 then the missing y values should be mapped to the last x value.
Here is the pseudo code (tried to capture the crux of the algorithm)
prevY = y1
for(i=x1+1;i<=x2;++i)
{
y = computeY(i);
if(diff(y,prevY)>1) dump_points(prevY,y,i);
prevY = y;
dump_point(i,y);
}
dump_points(prevY,y2,x2);
I am probably not covering all the cases here (esp. not the corner ones). But the idea is that for one value of x there would could be many values of y and vice versa depending on the slope of the line. The algorithm should consider this and generate all the points.

Resources