How to rotate 180 degrees an mtext() in R - r

Apparently, mtext() in R doesn't support the srt parameter whose job is to rotate a piece of text.
I need mtext() to create an axis title on side 4 of my moving plot (i.e., values to be plotted come from a function so they change and so do the plot axes values). I was wondering then, what options do I have to rotate 180 degrees this side 4 axis title?
An example is BELOW:
curve(dnorm(x),-3,3)
mtext("Strength",side=4,srt=180)

You can use par("usr") to obtain extremes of the plot area and use it to place your text without having to explicitly specify the x and y.
Try
curve(dnorm(x),-3,3)
corners = par("usr") #Gets the four corners of plot area (x1, x2, y1, y2)
par(xpd = TRUE) #Draw outside plot area
text(x = corners[2]+.5, y = mean(corners[3:4]), "Strength", srt = 270)
This way it will always be on the right extreme and vertically in the middle.

Related

Plotting in degrees instead of radians

I have plotted a graph that contains a trig function. Instead of having the x-axis be in radians, I would like it to be in degrees. It's a simple task of multiplying the displayed x-axis values by 180/!pi but I can't figure out how to do it. Let's say I'm trying to graph the cosine function as
q=plot(cos(x))
How can I change the displayed x-axis values to degrees?
Just pass the x-values to the plotting routine:
x = findgen(360)
y = cos(x * !dtor)
plot, x, y
Or, if you are using function graphics:
p = plot(x, y)

Plot in R out of proportion. Why?

I want to plot a world map in R, but for some reason there are unnecessary margins at the top and bottom of the image. I reduced the code to its minimal.
png('mundi.png',1000,500)
par(mar=c(0,0,0,0),bg='green')
plot(NA,xlim=c(-180,180),ylim=c(-90,90),xaxs='i',bty='n',xaxt='n',yaxt='n',asp=1)
par('usr')
rect(-180,-90,180,90,col='white')
dev.off()
The generated image is
The green areas are the unnecessary margins. The dimension of both the image and the coordinates are 2x1 (1000x500 and 360x180, respectively). xaxs='i' should make exact coordinates. asp=1 should not be needed, and is not making any difference. par('usr') is returning
-180.0 180.0 -97.2 97.2
Why isn't it returning
-180.0 180.0 -90.0 90.0
As it (supposedly) should?
You were almost there, actually. To control the limits of the plot window through xlim/ylim without the extra space R tends to add, you have to specify the x/yaxt = 'i' option. You set it for the x axis, but not the y axis.
When I do set it for the y axis, the values outputted are as expected, and the plot is completely white (forgive me for not putting up an image of it ;-) )
png('mundi.png', width = 1000, height = 500)
par(mar=c(0,0,0,0), bg='green')
plot(NA, xlim = c(-180,180), ylim = c(-90,90),
xaxs='i', yaxs='i', # set both axes to 'i' option
bty='n',xaxt='n',yaxt='n',asp=1)
par('usr')
# [1] -180 180 -90 90
rect(-180,-90,180,90,col='white')
dev.off()

How to add orientation (direction/angle/azimuth) to all points in scatterplot?

I am trying to create a scatter plot in R where each point has either an arrow or just a line indicating an "orientation" or a direction associated with that specific point. Each point has a different orientation but all of the orientation lines should be the same length. The angles range from 0-360 degrees with 0 being rightwards and then moving counter clockwise from there. The biggest problem is that my axes are in log scale and the x and y axes increase at different rates which throws off the orientation. My data is a 3x35 matrix with X,Y coordinates and my orientation angle in the third column.
I have tried using the arrows function; however, the arrows don't seem to be pointing in the correct direction and their lengths vary based on the angle. Here is the simple code I used:
plot(data$SF.X., data$TF.Y.,log="xy", pch=19, cex=0.8,ylim=c(0.031,20), xlim = c(0.031,1))
arrows(data$SF.X., data$TF.Y., x1=data$SF.X.+length*cos(data$Degrees), y1=data$TF.Y.+length*sin(data$Degrees),
code = 2, length=0.03, col="Red")
This the result of the above code:
Can someone point me in the right direction as to how to get my orientation lines all the same length and pointing in the correct direction based on the angle value in my third column?
Thank you so much!
Here is a sample of my data set:
x = c(0.47,0.80,0.09,0.78,0.14)
y = c(2.71,4.51,1.85,5.56,0.98)
orientation (degrees) = c(42.51,9.27,11.31,0.52,93.4)
For the angles, it's easy, R always works with angles in radians so you just have to multiply your degrees vector by pi/180.
For the length of the arrows, it is much more tricky. There is a deformation due to axis scale and image format so I came up with a workaround by normalizing the axis, then changing the labels and saving the figure in a perfect square format. Probably not the best solution but it gives the expected output.
x = c(0.47,0.80,0.09,0.78,0.14)
y = c(2.71,4.51,1.85,5.56,0.98)
degrees = c(42.51,9.27,11.31,0.52,93.4)
x.norm = (x-min(x))/(max(x)-min(x))
y.norm = (y-min(y))/(max(y)-min(y))
l <- 0.15
png("/home/ubuntu/Downloads/sample.png", width=500, height=500)
par(mar=c(4,4,1,1))
plot(x.norm, y.norm, pch=19, cex=0.8, col="Blue",
axes=FALSE, xlab="x", ylab="y", xlim=c(-0.1,1.1), ylim=c(-0.1,1.1))
arrows(x.norm, y.norm,
x1=x.norm+l*cos(degrees*pi/180), y1=y.norm+l*sin(degrees*pi/180),
length=0.05, col="Gray")
axis(1, at=seq(0,1,0.1), round(seq(min(x),max(x), (max(x)-min(x))/10),1))
axis(2, at=seq(0,1,0.1), round(seq(min(y),max(y), (max(y)-min(y))/10),1))
dev.off()

R: polygon does not align with curves

I made the plot below in R. The edges of the polygon should align with the two curves as they are plotted using the same vectors. Yet, the polygon is slightly higher on the Y-axis relative to the curves. I cannot figure out why.
How do I get the outer edges of the polygon to align with the two curves?
Similarly, why does the polygon not extend all the way too the right end of the two curves? The curves are somewhat loner than the polygon.
I realize that I can plot the polygon with borders and not plot the two lines. That does not solve the underlying problem. Both the polygon and the two curves are plotted using the upper and lower vectors so I think they should align exactly. They do not.
lower <- qchisq(0.05,0:100)
upper <- qchisq(0.95,0:100)
df <- (0:100)
plot(df,upper, type='n', axes=F)
polygon(c(0,df,rev(df)), c(0,upper,rev(lower)), col='grey75',border=NA)
axis(1,pos=0)
axis(2,pos=0, las=1)
lines(upper, col='black')
lines(lower,col='black')
lines assumes the index is 1:length(x) (where x is the input) when you don't specify a second argument.
But in your case it's 0:100. Add df as the first argument to lines:
lines(df, upper, col='black')
lines(df, lower, col='black')

Rotate plotted points of an ellipse to give a circle

I have an ellipse-shaped distribution that I think is a conic section. I want to rotate the points so that the distribution becomes circular-shaped, as if I was looking at the conic section directly over the top of the cone.
Here's some example data (generated using the function here)
X_df <-
structure(list(x = c(550.685479223573, 411.808342674744, 125.337513241526,
-46.6813176776531, 54.1090479024869, 335.045593380922, 538.806846993829,
476.123346783785, 207.359201714354, -23.3704356149293, -1.06902389582398,
252.471032092766, 502.461757269191, 522.09464005165, 290.954504794153,
22.4116013413886, -37.4399705577234, 166.122770874069, 446.874779008936,
547.271442128866, 372.271299246978, 84.7905677157295, -50.074206596271,
90.757431249567, 378.201298931732, 547.145608993239, 443.947162007208,
161.476775837252, -38.5517112166543, 25.2627436553199, 296.503160027896,
524.775126009974, 500.784559912938, 245.712512645379, -4.31860487373257,
-21.9661658669887, 211.218663607589, 479.198761786515, 535.314989389215,
330.010941011427, 50.0215808044216, -46.3823119064223, 130.383487121344,
416.170638042649, 549.268852072098, 407.813005658263, 119.940919946473,
-46.978590114418, 57.7409750579334, 340.505587064792, 539.650771180236,
472.254339573695, 201.890629521184, -25.163386210777, 1.25193046435474,
256.776302252232, 506.305676724803, 520.004964534048, 284.257495593069,
18.8183745840118, -35.9075114459174, 172.662124500953, 452.343060560759,
546.468842888411, 367.193523099128, 81.9151159445705, -49.726312730029,
95.1883131124973, 382.503271032958, 548.377552998115, 439.474201456606,
157.248088356873, -39.8634174011649, 28.665422852919, 301.243788141946,
526.815879166266, 497.683488701185, 240.939374274905, -7.78381612220116,
-19.3411744866129, 217.640180353188, 483.134755325255, 534.947529479343,
324.801587123232, 45.3957868762181, -45.0069945691924, 134.781896592204,
420.833721926428, 550.278658272823, 403.464000037755, 116.273973349216,
-48.5483252399878, 62.3918399072614, 345.924165684106, 540.282415561272,
468.621672005007, 195.304995872248, -28.2738679786754, 4.25351768918281,
262.272866287766, 509.296144374104), y = c(150.522375543584,
317.792592638159, 332.783726315973, 177.890614907595, -1.30774215535761,
-41.9959828735621, 94.0557252742373, 281.491416261009, 347.931229803675,
232.411150772918, 41.2498141860971, -50.240758928064, 42.4333078345691,
233.202857825371, 347.930304275537, 279.801242902484, 93.7702821671593,
-42.9605564915062, -0.128821245055916, 179.228629398932, 331.853832274807,
317.39347890031, 147.731418574477, -19.2449921421865, -31.3298018420377,
123.222814177221, 301.499351173211, 340.662811705721, 204.270915882133,
17.5570334546183, -47.8527634953491, 69.1925023774197, 260.846781070028,
350.702299892942, 255.267980339802, 64.3048063206447, -47.7550214881633,
21.0575085383169, 209.247480999408, 342.716023607699, 298.578792586917,
118.053124236616, -33.3190320226709, -16.5618829502486, 154.097078032767,
319.940208485997, 330.141085013461, 175.063055837321, -4.17911647131882,
-40.77087978947, 96.7492568480405, 284.629419943293, 347.18869555741,
228.951107374031, 37.6230640656836, -49.9549156886126, 45.2896584936418,
236.96620488459, 349.2183672397, 277.259838492706, 88.5019845874813,
-43.1419505604449, 1.98249146234145, 183.766146834555, 334.721418603224,
314.869389642466, 144.917094343997, -21.0615467657252, -29.137753346726,
126.928148173889, 305.196445845808, 339.338402720207, 201.609402013064,
15.0779976117978, -47.1046400880924, 71.7191693530443, 263.543031729657,
350.145628648054, 252.792513384296, 61.2531942049295, -49.0697852698499,
24.2068045114243, 212.793083656477, 343.533262533366, 295.969945687212,
115.135250419503, -34.4145910896749, -14.7817206225652, 156.282366465729,
322.116360452784, 328.626788731125, 171.323808201914, -6.54021515590322,
-40.1360134761796, 101.492490333309, 286.854230399582, 347.010792855229,
226.829162028581, 35.3880363162166, -50.8418314561365, 48.893760376765
)), .Names = c("x", "y"), row.names = c(NA, -101L), class = "data.frame")
Plot the ellipse, this resembles my actual data:
ggplot(X_df, aes(x, y)) +
geom_point() +
coord_equal()
I want to apply a function to the xy coords to rotate the ellipse around its long axis, moving the top of the ellipse towards me, and the bottom of the ellipse away from me, to get something like this (with equal dimension along the x-axis as the ellipse above, but different dimension along the y-axis):
I want to rotate my data like this ellipse is rotated to produce the circle, where I see the maximum distance between the top and bottom of the shape (ie. the longest possible axis perpendicular to the long axis), as the shape rotates around it long axis.
How can I do that?
It seems like what you're saying is that if I viewed the "circle" edge on from, say, x=-1000, y=0, I would see a line rotated counterclockwise (out of the xy-plane) away from the y axis. The goal is to rotate the circle back to the y-axis.
The angle of rotation is acos(1/ratio) (0.839 radians or 48.06 degrees in this case) where ratio is diff(range(X_df$x))/diff(range(X_df$y)) (assuming the axis of rotation is in the xy-plane and parallel to the x-axis and your data includes points on the x axis on both sides of the circle).
To, in effect, rotate the circle back to the xy-plane, you could just multiply the y points by ratio and then, to maintain the same center, subtract (ratio - 1) * mean(X_df$y) (where I've assumed the data points are evenly distributed about the circle).
In other words (or in code, actually):
ratio = diff(range(X_df$x))/diff(range(X_df$y))
X_df$ynew = ratio * X_df$y - (ratio - 1) * mean(X_df$y)
ggplot(X_df, aes(x, ynew)) +
geom_point() +
coord_equal()
Compare original to "rotated":

Resources