It might be silly question. But I want the clarification.
If X follows lognormal then log(X) follows normal distribution
I want to know dlnorm is not equal to dnorm, why?? But plnorm is equal to pnorm!!!
> u=5
> s=0.5
> u
[1] 5
> s
[1] 0.5
> T=84.5
> dist_log=plnorm(T, meanlog=u, sdlog=s)
> dist_log
[1] 0.1299776194
> dist_norm=pnorm(log(T), mean=u, sd=s)
> dist_norm
[1] 0.1299776194
> den_log=dlnorm(T, meanlog=u, sdlog=s)
> den_log
[1] 0.005006388135
> den_norm=dnorm(log(T), mean=u, sd=s)
> den_norm
[1] 0.4230397974
You're right that the probability functions pnorm() and plnorm() will give the same results, given an appropriate data transformation, and that's an important insight. However, dnorm() and dlnorm() will not.
Here's another way to think of it: the d__ functions return the height of a curve at a given point, and the p__ functions return the area under the curve. Statistically, the d__ functions aren't often much use to us by themselves, since the curve height doesn't really mean anything. In fact, the curve itself is scaled so that the total area underneath is 1. What does typically matter is area - and the area of given regions corresponds to probability.
Here's a visual that will hopefully help...
curve(dnorm(x,mean=5,sd=0.5), from=0, to=10)
abline(v=log(84.5))
points(x=log(84.5), y=dnorm(log(84.5), mean=5, sd=0.5))
curve(dlnorm(x,meanlog=5,sdlog =0.5), from=0, to=600)
abline(v=84.5)
points(x=84.5, y=dlnorm(84.5, meanlog=5, sdlog=0.5))
The area to the left of the vertical line is the same in both plots, but the height of the curve at that point is different.
Related
I'm interested in a fast way to calculate the rotation-independent center of a simple, convex, (non-intersecting) 2D polygon.
The example below (on the left) shows the mean center (sum of all points divided by the total), and the desired result on the right.
Some options I've already considered.
bound-box center (depends on rotation, and ignores points based on their relation to the axis).
Straight skeleton - too slow to calculate.
I've found a way which works reasonably well, (weight the points by the edge-lengths) - but this means a square-root call for every edge - which I'd like to avoid.(Will post as an answer, even though I'm not entirely satisfied with it).
Note, I'm aware of this questions similarity with:What is the fastest way to find the "visual" center of an irregularly shaped polygon?
However having to handle convex polygons increases the complexity of the problem significantly.
The points of the polygon can be weighted by their edge length which compensates for un-even point distribution.
This works for convex polygons too but in that case the center point isn't guaranteed to be inside the polygon.
Psudo-code:
def poly_center(poly):
sum_center = (0, 0)
sum_weight = 0.0
for point in poly:
weight = ((point - point.next).length +
(point - point.prev).length)
sum_center += point * weight
sum_weight += weight
return sum_center / sum_weight
Note, we can pre-calculate all edge lengths to halve the number of length calculations, or reuse the previous edge-length for half+1 length calculations. This is just written as an example to show the logic.
Including this answer for completeness since its the best method I've found so far.
There is no much better way than the accumulation of coordinates weighted by the edge length, which indeed takes N square roots.
If you accept an approximation, it is possible to skip some of the vertices by curve simplification, as follows:
decide of a deviation tolerance;
start from vertex 0 and jump to vertex M (say M=N/2);
check if the deviation along the polyline from 0 to M exceeds the tolerance (for this, compute the height of the triangle formed by the vertices 0, M/2, M);
if the deviation is exceeded, repeat recursively with 0, M/4, M/2 and M/2, 3M/4, M;
if the deviation is not exceeded, assume that the shape is straight between 0 and M.
continue until the end of the polygon.
Where the points are dense (like the left edge on your example), you should get some speedup.
I think its easiest to do something with the center of masses of the delaunay triangulation of the polygon points. i.e.
def _centroid_poly(poly):
T = spatial.Delaunay(poly).simplices
n = T.shape[0]
W = np.zeros(n)
C = 0
for m in range(n):
sp = poly[T[m,:],:]
W[m] = spatial.ConvexHull(sp).volume
C += W[m] +np.mean(sp, axis = 0)
return C / np.sum(W)
This works well for me!
So here's a little bit of geometry for you. I've been stuck on this for a while now:
I need to write a script (in C#, but feel free to answer in whatever script you'd like) that generates random points. A points has to values, x and y.
I must generate N points total (where N > 1 and is also randomly up to 100).
point 1 must be x = 0, y = 0. point 2 must be of distance 1 from point 1. So that Root(x2 + y2) = 1.
point 3 must be of distance 1 from point 2 and so on and so forth.
Now here's the tricky part - point N must be of distance 1 from point 1. So if you were to connect all points into a single shape, you'd get a closed shape with each vertices being the same length.
(vertices may cross and you may even have two points at exactly the same location. As long as it's random).
Any idea how you'd do that?
I would do it with simulation of chain there are 2 basic ways one is start from regular polygon and then randomize one point a bit (rotate a bit) then iterate the rest to maintain the segment size=1.
The second one is start with full random open chain (like in MBo answer) and then iteratively change the angles until the last point is on desired distance from first point. I think the second approach is a bit simpler to code...
If you want something more complicated then you can generate M random points and handle them as closed Bezier curve cubic patches loop control points. Then just find N equidistant points on it (this is hard task) and rescale the whole thing to match segment line size = 1
If you want to try first approach then
Regular polygon start (closed loop)
Start with regular polygon (equidistant points on circle). So divide circle to N angular segments. Select radius r so line length match l=1
so r=0.5/cos(pi/N) ... from half angle triangle
Make function to rotate i-th point by some single small step
So just rotate the i-th point around (i-1)th point with radius 1 and then iteratively change the {i+1,...N} points to match segments sizes
you can exploit symmetry to avoid bullet #2
but this will lead not to very random result for small N. Just inverse rotation of 2 touching segments for random point p(i) and loop this many times.
to make it more random you can apply symmetry on whole parts (between 2 random points) instead of on 2 lines only
The second approach is like this:
create randomized open chain (like in MBo's answer)
so all segments are already with size=1.0. Remember also the angle not just position
i-th point iteration
for simplicity let the points be called p1,p2,...pn
compute d0=||pn-p1|-1.0|
rotate point pi left by some small da angle step
compute dl=||pn-p1|-1.0|
rotate point pi right by 2.0*da
compute dr=||pn-p1|-1.0|
rotate point pi to original position ... left by da
now chose direction closer to the solution (min dl,dr,d0) so:
if d0 is minimal do not change this point at all and stop
if dl is minimal then rotate left by da while dl is lowering
if dr is minimal then rotate right by da while dr is lowering
solution
loop bullet #2 while the d=||pn-p0|-1.0| is lowering then change da to da*=0.1 and loop again. Stop if da step is too small or no change in d after loop iteration.
[notes]
Booth solutions are not precise your distances will be very close to 1.0 but can be +/- some error dependent on the last da step size. If you rotate point pi then just add/sub angle to all pi,pi+1,pi+2,..pn points
Edit: This is not an answer, closeness has not been taken into account.
It is known that Cos(Fi)^2 + Sin(Fi)^2 = 1 for any angle Fi
So you may use the next approach:
P[0].X = 0
P[0].Y = 0
for i = 1 .. N - 1:
RandomAngle = 2 * Pi * Random(0..1)
P[i].X = P[i-1].X + Cos(RandomAngle)
P[i].Y = P[i-1].Y + Sin(RandomAngle)
I am trying to generate a certain amount of random uniform points inside a rectangle (I know the pair of coordinates for each corner).
Let our rectangle be
ABCD
My idea is:
Divide the rectangle into two triangles by the AC diagonal. Find the slope and the intercept of the diagonal.
Then, generate two random numbers from [0,1] interval, let them be a,b.
Evaluate x = aAB and y = bAD (AB, AD, distances). If A is not (0,0), then we can add to x and y A's coordinates.
Now we have a point (x,y). If it is not in the lower triangle (ABC), skip to the next step.
Else, add the point to our plot and also add the symmetric of (x,y) vs. the AC diagonal so that we can fill the upper triangle (ADC) too.
I have implemented this, but I highly doubt that the points are uniformly generated (judging from the plot). How should I modify my algorithm? I guess that the issue is related to how I pick the triangle and the symmetric thing.
Why not just generate x=random([A.x, B.x]) and y=random([B.y, C.y]) and put them together as (x,y)? A n-dimensional uniform distribution is simply the product of the n uniform distributions of the components.
This is referred to as point picking and other similar terms. You seem to be on the right track in that the points should come from the uniform distribution. Your plot looks reasonably random to me.
What are you doing with upper and lower triangles? They seem unnecessary and would certainly make things less random. Is this some form variance reduction along the lines of antithetic variates? If #Paddy3118 is right an you really just need random-ish points to fill the space, then you should look into low-discrepancy sequences. The Halton sequence generalizes the van der Corput sequence to multiple dimensions. If you have Matlab's Statistics Toolbox check out the sobolset and haltonset functions or qrandstream and qrand.
This approach (from #Xipan Xiao & #bonanova.) should be reproducible in many languages. MATLAB code below.
a = 0; b = 1;
n = 2000;
X = a + (b-a)*rand(n,1);
Y = a + (b-a)*rand(n,1);
Newer versions of MATLAB can make use of the makedist and random commands.
pdX = makedist('Uniform',a,b);
pdY = makedist('Uniform',a,b);
X = random(pdX,n,1);
Y = random(pdY,n,1);
The points (X,Y) will be uniformly in the rectangle with corner points (a,a), (a,b), (b,a), (b,b).
For verification, we can observe the marginal distributions for X and Y and see that those are uniform as well.
scatterhist(X,Y,'Marker','.','Direction','out')
Update: Using haltonset (suggested by #horchler)
p = haltonset(2);
XY = net(p,2000);
scatterhist(XY(:,1),XY(:,2),'Marker','.','Direction','out')
If you are after a more uniform density then you might consider a Van der Corput sequence. The sequence finds use in Monte-Carlo simulations and Wolfram Mathworld calls them a quasi-random sequence.
Generate two random numbers in the interval [0,1] translate and scale them to your rectangle as x and y.
There is just my thought, i haven't test with code yet.
1.Divide the rectangle to grid with N x M cells, depends on variable density.
2.loop through the cell and pick a random point in the cell until it reached your target point quantity.
Since I was 13 and playing around with AMOS 3D I've been wanting to learn how to code 3D graphics. Now, 10 years later, I finally think I have have accumulated enough maths to give it a go.
I have followed various tutorials, and defined screenX (and screenY, equivalently) as
screenX = (pointX * cameraX) / distance
(Plus offsets and scaling.)
My problem is with what the distance variable actually refers to. I have seen distance being defined as the difference in z between the camera and the point. However, that cannot be completely right though, since x and y have the same effect as z on the actual distance from the camera to the point. I implemented distance as the actual distance, but the result gives a somewhat skewed perspective, as if it had "too much" perspective.
My "actual distance" implementation was along the lines of:
distance = new Vector(pointX, pointY, cameraZ - pointZ).magnitude()
Playing around with the code, I added an extra variable to my equation, a perspectiveCoefficient as follows:
distance = new Vector(pointX * perspectiveCoefficient,
pointY * perspectiveCoefficient, cameraZ - pointZ).magnitude()
For some reason, that is beyond me, I tend to get the best result setting the perspectiveCoefficient to 1/sqrt(2).
My 3D test cube is at http://vega.soi.city.ac.uk/~abdv866/3dcubetest/3dtest.svg. (Tested in Safari and FF.) It prompts you for a perspectiveCoefficient, where 0 gives a perspective without taking x/y distance into consideration, and 1 gives you a perspective where x, y and z distance is equally considered. It defaults to 1/sqrt(2). The cube can be rotated about x and y using the arrow keys. (For anyone interested, the relevant code is in update() in the View.js file.)
Grateful for any ideas on this.
Usually, projection is done on the Z=0 plane from an eye position behind this plane. The projected point is the intersection of the line (Pt,Eye) with the Z=0 plane. At the end you get something like:
screenX = scaling * pointX / (1 + pointZ/eyeDist)
screenY = scaling * pointY / (1 + pointZ/eyeDist)
I assume here the camera is at (0,0,0) and eye at (0,0,-eyeDist). If eyeDist becomes infinite, you obtain a parallel projection.
Given a "shape" drawn by the user, I would like to "normalize" it so they all have similar size and orientation. What we have is a set of points. I can approximate the size using bounding box or circle, but the orientation is a bit more tricky.
The right way to do it, I think, is to calculate the majoraxis of its bounding ellipse. To do that you need to calculate the eigenvector of the covariance matrix. Doing so likely will be way too complicated for my need, since I am looking for some good-enough estimate. Picking min, max, and 20 random points could be some starter. Is there an easy way to approximate this?
Edit:
I found Power method to iteratively approximate eigenvector. Wikipedia article.
So far I am liking David's answer.
You'd be calculating the eigenvectors of a 2x2 matrix, which can be done with a few simple formulas, so it's not that complicated. In pseudocode:
// sums are over all points
b = -(sum(x * x) - sum(y * y)) / (2 * sum(x * y))
evec1_x = b + sqrt(b ** 2 + 1)
evec1_y = 1
evec2_x = b - sqrt(b ** 2 + 1)
evec2_y = 1
You could even do this by summing over only some of the points to get an estimate, if you expect that your chosen subset of points would be representative of the full set.
Edit: I think x and y must be translated to zero-mean, i.e. subtract mean from all x, y first (eed3si9n).
Here's a thought... What if you performed a linear regression on the points and used the slope of the resulting line? If not all of the points, at least a sample of them.
The r^2 value would also give you information about the general shape. The closer to 0, the more circular/uniform the shape is (circle/square). The closer to 1, the more stretched out the shape is (oval/rectangle).
The ultimate solution to this problem is running PCA
I wish I could find a nice little implementation for you to refer to...
Here you go! (assuming x is a nx2 vector)
def majAxis(x):
e,v = np.linalg.eig(np.cov(x.T)); return v[:,np.argmax(e)]