Related
I need to plot randonmly a set of points is a 5X5 grid.
basically I need to plot a set of 2 points (can be horizontaly or verticaly), and a set of other 3 points, is a 5x5 grid.
the position of the points should be randomly attributed.
at the end it should look like something like this (i can do in a "static" code, but i cannot do it as a random atributtion)
par(xaxs = "i", yaxs = "i")
plot.new()
plot.window(xlim = c(0.5, 5.5), ylim = c(0.5, 5.5))
grid(nx = 5, ny = 5, col = "black", lty = "dashed")
box(lwd = 1)
# PLot points
points(1, 5, pch = 16, col = "blue", cex = 1.5)
points(2, 5, pch = 16, col = "blue", cex = 1.5)
points(1, 1, pch = 16, col = "pink", cex = 1.5)
points(1, 2, pch = 16, col = "pink", cex = 1.5)
points(1, 3, pch = 16, col = "pink", cex = 1.5)
This function will perform the algorithm. It does so by enumerating all possible valid pairs of blue dots (there are only 40) and valid triples of pink dots (there are only 30). It then samples a valid set of blue dots, then repeatedly samples random sets of pink dots until there are no clashes. It then uses your plotting code to draw the result:
random_points <- function() {
blue_pos <- cbind(c(1:20, c(1:25)[-c(5, 10, 15, 20, 25)]),
c(6:25, c(1:25)[-c(1, 6, 11, 16, 21)]))
pink_pos <- cbind(c(1:15, 1:3, 6:8, 11:13, 16:18, 21:23),
c(6:20, 2:4, 7:9, 12:14, 17:19, 22:24),
c(11:25, 3:5, 8:10, 13:15, 18:20, 23:25))
blue <- pink <- blue_pos[sample(nrow(blue_pos), 1),]
while(any(pink %in% blue)) pink <- pink_pos[sample(nrow(pink_pos), 1),]
par(xaxs = "i", yaxs = "i")
plot.new()
plot.window(xlim = c(0.5, 5.5), ylim = c(0.5, 5.5))
grid(nx = 5, ny = 5, col = "black", lty = "dashed")
box(lwd = 1)
for(i in 1:2) points(1 + (blue[i] - 1) %% 5,
1 + (blue[i] - 1) %/% 5,
pch = 16, col = "blue", cex = 1.5)
for(i in 1:3) points(1 + (pink[i] - 1) %% 5,
1 + (pink[i] - 1) %/% 5,
pch = 16, col = "pink", cex = 1.5)
}
Testing it out randomly 9 times gives us:
par(mfrow = c(3, 3))
for(i in 1:9) random_points()
I want to create some sort of radar chart but without using ggplot2 or fmsb.
Sample chart:
d1 <- 1:10
names(d1) <- LETTERS[1:10]
rChart <- function(N = 7, R = 1, border = NA, density = NA, angle = 45,
col = rgb(1, 0, 0, 0.5), lty = 2, lwd = 1){
if (N >=3){
alpha <- c(0, 2*pi*(1:N)/N)
x <- R*cos(alpha)
y <- R*sin(alpha)
if (length(dev.list()) == 0){
plot(x, y, type="n")
}
polygon(x, y, col = col, border = border, density = density, angle = angle)
lines(x, y, lty = lty, lwd = lwd, col = col)
}
}
# drawing two circles in one plot
rChart(N = 100, R = 8, density = 10, col = rgb(0, 1, 0, 0.4), lty = 2, lwd = 3)
rChart(N = 100, R = 6, density = 10, col = rgb(0, 1, 0, 0.4), lty = 2, lwd = 3)
Can I implement for loop to create polygon inscribed into circles and then place labels similiar as in the example above?
This code gets the data needed to make two different lines. I was wondering if there was a way to see if two lines intersected easily.
# generate data
red <- matrix(runif(n = 4, min = 0, max = 1), nrow = 2)# gets the 4 points for the first line
blue <- matrix(runif(n = 4, min = 0, max = 1), nrow = 2)# gets the 4 points for second line
# make a plot
plot(red, col = "red", pch = 16, cex = 2,
asp = 1, xlim = c(0,1), ylim = c(0,1),
xlab = "", ylab = "")##plots both points red
abline(v = c(0,1), col = "grey", lty = 2)
abline(h = c(0,1), col = "grey", lty = 2)
segments(red[1,1], red[1,2], red[2,1], red[2,2], lwd = 2, col = "red")#Makes the line segment
points(blue, col = "blue", pch = 16, cex = 2,
asp = 1, xlim = c(0,1), ylim = c(0,1))# does same thing for blue line
segments(blue[1,1], blue[1,2], blue[2,1], blue[2,2], lwd = 2, col = "blue")
##makes all of the plots and can see if the plot intersects.`
Here's a practical answer using simple algebra wrapped up in a function.
The process is to find the slope and y intercept of both lines, and solve simultaneous equations to find the intersection. If both line segments have the same gradient the answer is undefined so return NA.
Return the x, y co-ordinates of the intersection if it is within the x range of one of the line segments, otherwise return NA
check_intersect <- function(mat1, mat2)
{
dy1 <- mat1[,2][which.max(mat1[,1])] - mat1[,2][which.min(mat1[,1])]
dy2 <- mat2[,2][which.max(mat2[,1])] - mat2[,2][which.min(mat2[,1])]
dx1 <- max(mat1[,1]) - min(mat1[,1])
dx2 <- max(mat2[,1]) - min(mat2[,1])
m1 <- dy1/dx1
m2 <- dy2/dx2
if(m1 == m2) return(NA)
c1 <- mat1[1, 2] - m1 * mat1[1, 1]
c2 <- mat2[1, 2] - m2 * mat2[1, 1]
x <- (c2 - c1)/(m1 - m2)
y <- m1 * x + c1
if(x > min(mat1[,1]) & x < max(mat1[,1]))
return(c(x, y))
else
return(NA)
}
Now test this with a reprex:
set.seed(123)
red <- matrix(runif(n = 4, min = 0, max = 1), nrow = 2)# gets the 4 points for the first line
blue <- matrix(runif(n = 4, min = 0, max = 1), nrow = 2)# gets the 4 points for second line
# make a plot
plot(red, col = "red", pch = 16, cex = 2,
asp = 1, xlim = c(0,1), ylim = c(0,1),
xlab = "", ylab = "")##plots both points red
abline(v = c(0,1), col = "grey", lty = 2)
abline(h = c(0,1), col = "grey", lty = 2)
segments(red[1,1], red[1,2], red[2,1], red[2,2], lwd = 2, col = "red")#Makes the line segment
points(blue, col = "blue", pch = 16, cex = 2,
asp = 1, xlim = c(0,1), ylim = c(0,1))# does same thing for blue line
segments(blue[1,1], blue[1,2], blue[2,1], blue[2,2], lwd = 2, col = "blue")
p <- check_intersect(red, blue)
points(p[1], p[2], cex = 2)
p
#> [1] 0.5719010 0.6781469
Created on 2020-03-24 by the reprex package (v0.3.0)
I have code producing the below pasted plot
x <- c(2, 3, 4)
y <- c(2.5, 4.1, 5.5)
plot(x, y, type = "o", xlim = c(1, 5), ylim = c(2, 6), axes = FALSE, bty = "n")
axis(side = 1, at = seq(1, 5, 1))
axis(side = 2, at = seq(2, 6, 1), las = 2)
I would like to have neither ticks nor labels at position 1 and 5, but the axis should still be drawn. This is what I am looking for:
When using labels = c("", 2, 3, 4, "") ticks are drawn. When using tick = FALSE, I get no axis. Does anybody have a solution for this?
You just need to draw the line manually. Using the line2user function in this answer:
x <- c(2, 3, 4)
y <- c(2.5, 4.1, 5.5)
plot(x, y, type = "o", xlim = c(1, 5), ylim = c(2, 6), axes = FALSE, bty = "n")
axis(side = 1, at = 2:4)
lines(x = c(1, 5), y = rep(line2user(0, side = 1), 2), xpd = TRUE)
axis(side = 2, at = seq(2, 6, 1), las = 2)
Note, the line2user function just gives the position of the lines in the user coordinate system. You need the xpd = TRUE to draw outside the plotting region.
I have one plot and i need to adjust legends in a row. How can i do it?
plot(x,y)
legend(c("x","y"))
I need legend should be in one line
----- x --------- y
Regards
You want to set horiz=TRUE in legend. Here's a comparison of the default behavior (horiz=FALSE) to horiz=TRUE.
This plot is based on the second example from the legend documentation:
layout(matrix(1:2,nrow=1))
# `horiz=FALSE` (default behavior)
plot(x, sin(x), type = "l", ylim = c(-1.2, 1.8), col = 3, lty = 2, main="horiz=FALSE (Default)")
points(x, cos(x), pch = 3, col = 4)
lines(x, tan(x), type = "b", lty = 1, pch = 4, col = 6)
legend(-1, 1.9, c("sin", "cos", "tan"), col = c(3, 4, 6),
text.col = "green4", lty = c(2, -1, 1), pch = c(NA, 3, 4),
merge = TRUE, bg = "gray90")
# `horiz=TRUE`
plot(x, sin(x), type = "l", ylim = c(-1.2, 1.8), col = 3, lty = 2, main="horiz=TRUE")
points(x, cos(x), pch = 3, col = 4)
lines(x, tan(x), type = "b", lty = 1, pch = 4, col = 6)
legend(-1, 1.9, c("sin", "cos", "tan"), col = c(3, 4, 6),
text.col = "green4", lty = c(2, -1, 1), pch = c(NA, 3, 4),
merge = TRUE, bg = "gray90", horiz=TRUE)