How to plot dices, that change with the result - r

I am trying to do a yahtzee game in R, amd I would like to show the dice on the plot part of R. like this :
I have this function how simulate a dice roll
rolls_the_dice <- function(X1 = 5){if(X1 <= 5){sample(1:6, X1, replace = TRUE)}
But I don't know how to display the score the way I described. I have two main ideas:
First:
plot(c(0, 200), c(0, 170), type = "n", xlab = "", ylab = "", axes= F, main = "")
rect(xleft = 30, xright = 80, ybottom = 0, ytop = 50)
rect(xleft = 0, xright = 50, ybottom = 100, ytop = 150)
rect(xleft = 70, xright = 120, ybottom = 100, ytop = 150)
rect(xleft = 140, xright = 190, ybottom = 100, ytop = 150)
rect(xleft = 120, xright = 170, ybottom = 0, ytop = 50)
That plot 5 rectangles, and then I have to find a way to put points in it giving the result
Second :
rect(xleft = 0, xright = 20, ybottom = 0, ytop = 20)
points(x= 10, y= 10, col="black", pch=19)
This is the face one of a dice. This idea is to create one plot per dice face, and then to pick them up giving the result. But here I donĀ“t know how to store them.
If somebody could tell me what is the best (or even just the feasable) idea.

there's a package for that ;-)
library(magrittr)
library(tidydice)
roll_dice(times = 5, rounds = 1) %>% plot_dice()

Here is one way of doing it in base R using lists...
#your function
rolls_the_dice <- function(X1 = 5){if(X1 <= 5){sample(1:6, X1, replace = TRUE)}}
#a list of x-y coordinates of the corners of the five dice
rects <- list(c(30, 0), c(0, 100), c(70, 100), c(140, 100), c(120, 0))
#a list of list(x, y) coordinates of the dots for numbers 1-6
dots <- list(list(0, 0),
list(c(-1, 1), c(-1, 1)),
list(c(-1, 0, 1), c(-1, 0, 1)),
list(c(-1, -1, 1, 1), c(-1, 1, -1, 1)),
list(c(-1, -1, 0, 1, 1), c(-1, 1, 0, -1, 1)),
list(c(-1, -1, -1, 1, 1, 1), c(-1, 0, 1, -1, 0, 1)))
#a function to plot a dice and a number
plot_face <- function(rects, dots){
rect(xleft = rects[1], xright = rects[1] + 50,
ybottom = rects[2], ytop = rects[2] + 50)
points(x = rects[1] + 25 + 15 * dots[[1]],
y = rects[2] + 25 + 15 * dots[[2]], col = "black", pch = 19)
}
#plot a blank area (note asp=1 to keep the dice square)
plot(c(0, 200), c(0, 170), type = "n", xlab = "", ylab = "",
axes= F, main = "", asp = 1)
#plot the five dice and five random numbers
mapply(plot_face, rects, dots[rolls_the_dice()])

Maybe this could be also interesting for you: the 'TeachingDemos' package provides a "dice" function code https://github.com/cran/TeachingDemos
#install.packages("TeachingDemos")
library(TeachingDemos)
dice(5,1, plot.it=TRUE)

Related

Histogram bins cut off along x-axis when using diag.panel argument in pairs() function

I am trying to create a scatter plot matrix following the cookbook recipe found at https://r-graphics.org/recipe-scatter-splom. However, 3 of the 4 histograms are cut off either on the left, right, or both sides of the x-axis. How do I prevent this from happening? Code below:
dftest <- structure(list(eOver = c(29, 14, 12, 11, 9, 47, 29, 12, 24, 30, 23, 20),
eUnder = c(31, 43, 67, 66, 61, 83, 56, 67, 69, 63, 55, 69),
nHerb = c(8, 31, 7, 9, 2, 3, 2, 21, 11, 3, 6, 15),
nUnder = c(3, 0, 2, 0, 0, 4, 2, 2, 3, 4, 1, 1)),
row.names = c(NA, 12L),
class = "data.frame")
panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor, ...) {
usr <- par("usr")
on.exit(par(usr))
par(usr = c(0, 1, 0, 1))
r <- abs(cor(x, y, use = "complete.obs"))
txt <- format(c(r, 0.123456789), digits = digits)[1]
txt <- paste(prefix, txt, sep = "")
if (missing(cex.cor)) cex.cor <- 0.8/strwidth(txt)
text(0.5, 0.5, txt, cex = cex.cor * (1 + r) / 2)
}
panel.hist <- function(x, ...) {
usr <- par("usr")
on.exit(par(usr))
par(usr = c(usr[1:2], 0, 1.5) )
h <- hist(x, plot = FALSE)
breaks <- h$breaks
nB <- length(breaks)
y <- h$counts
y <- y/max(y)
rect(breaks[-nB], 0, breaks[-1], y, col = "white", ...)
}
panel.lm <- function (x, y, col = par("col"), bg = NA, pch = par("pch"),
cex = 1, col.smooth = "black", ...) {
points(x, y, pch = pch, col = col, bg = bg, cex = cex)
abline(stats::lm(y ~ x), col = col.smooth, ...)
}
pairs(dftest,
upper.panel = panel.cor,
diag.panel = panel.hist,
lower.panel = panel.lm
)
Problem plot

Minor issue with plot in base R - unwanted lines showing at top of plot

I have created a plot in base R, including 3 clipped 'ablines'. Despite using the "frame.plot = FALSE" function, which removes the box around the plot (see image example1), when I add my clipped ablines [using ablineclip] new framing lines appear above them (see image example2).
The code I am using is shown below:
library(plotrix)
op <- par(mar=c(5, 6, 4, 2) + 0.1)
plot(dif2$land_area ~ dif2$Year_no, ylim = c(1,4000), col.axis = rgb(68, 84, 106,max=255),xaxt='n', type='o', pch=16, col='red', font.axis=2, font.lab=2, col.lab=rgb( 113, 113, 113, max=255), xlab = 'Year', ylab = 'Total Land Area Changed to \nResidential Development (Ha)', frame.plot = FALSE, cex=1.3)
rect(23.2,0,25.8,4000,col='grey',density = 8,border=T)
rect(10.2,0,11.8,4000,col='grey',density = 8,border=T)
xlim(0,30)
axis(1,at= 1:30,labels=F)
axis(1,at= 1:30,tick=F, font.axis=2, col.axis = rgb(68, 84, 106, max=255),labels= c(1989:2018))
# the below section is that which seems to create the issue #
ablineclip(lm(land_area ~ Year_no, data = subset(dif2, int==0)), col='blue', lty=2, x1=1,x2=10, lwd=0.8)
ablineclip(lm(land_area ~ Year_no, data = subset(dif2, int==0)), col='blue', lty=2, x1=12,x2=23, lwd=0.8)
ablineclip(lm(land_area ~ Year_no, data = subset(dif2, int==1)), col='blue', lty=2, x1=26,x2=30, lwd=0.8)
Does anyone have any ideas of why the ablineclip function appears to be altering the borders of the plot?
Cheers
You just need to set the y limits to the area clipped by ablineclip using the parameters y1 and y2, ensuring that y2 is below the top of your plot.
ablineclip(lm(land_area ~ Year_no, data = subset(dif2, int==0)),
col = 'blue', lty = 2, x1 = 1, x2 = 10, y1 = 1, y2 = 3500, lwd = 0.8)
ablineclip(lm(land_area ~ Year_no, data = subset(dif2, int==0)),
col = 'blue', lty = 2, x1 = 12, x2 = 23, y1 = 1, y2 = 3500, lwd = 0.8)
ablineclip(lm(land_area ~ Year_no, data = subset(dif2, int==1)),
col = 'blue', lty = 2, x1 = 26, x2 = 30, y1 = 1, y2 = 3500, lwd = 0.8)
Result:
Of course, I didn't have your data to work with so I had to make up a set that was similar (that's why the graph's shape is different to yours). The data I used was:
dif2 <- structure(list(Year_no = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28), land_area = c(3165, 3179, 3076, 2772, 2816, 2605, 2565,
2525, 2446, 2361, NA, 1966, 1911, 1790, 1819, 1710, 1673, 1555,
1434, 1220, 1174, 1021, 1564, NA, NA, 2479, 2539, 2872), int = c(0,
0, 0, 0, 0, 0, 0, 0, 0, 0, NA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, NA, NA, 1, 1, 1)), row.names = c(NA, -28L), class = "data.frame")
It's something in the code, see below, when you provide x1 and x2, it draws a line on the y limits + 1 :
> ablineclip
function (a = NULL, b = NULL, h = NULL, v = NULL, reg = NULL,
coef = NULL, untf = FALSE, x1 = NULL, x2 = NULL, y1 = NULL,
y2 = NULL, ...)
{
if (!is.null(c(x1, x2, y1, y2))) {
oldclip <- par("usr")
if (is.null(x1))
x1 <- oldclip[1]
if (is.null(x2))
x2 <- oldclip[2]
if (is.null(y1))
y1 <- oldclip[3]
if (is.null(y2))
y2 <- oldclip[4]
clip(x1, x2, y1, y2)
abline(h = oldclip[4] + 1)
You can hack the code and comment out this line, or just use abline with a combination of predict. First we simulate something like your data:
set.seed(123)
dif2 = data.frame(land_area= rnbinom(30,mu=1500,size=5),
Year_no = seq_along(1989:2018))
dif2$int = rep(0:1,c(23,7))
dif2$int[23:27] = 1
dif2[1989:2018 %in% c(1999,2012,2013),c("land_area","int")] = NA
And plot:
library(plotrix)
op <- par(mar=c(5, 6, 4, 2) + 0.1)
plot(dif2$Year_no, dif2$land_area,ylim = c(1,4000), col.axis = rgb(68, 84, 106,max=255),xaxt='n', type='o', pch=16, col='red', font.axis=2, font.lab=2, col.lab=rgb( 113, 113, 113, max=255), xlab = 'Year', ylab = 'Total Land Area Changed to \nResidential Development (Ha)', frame.plot = FALSE, cex=1.3)
rect(23.2,0,25.8,4000,col='grey',density = 8,border=T)
rect(10.2,0,11.8,4000,col='grey',density = 8,border=T)
axis(1,at= 1:30,labels=F)
axis(1,at= 1:30,tick=F, font.axis=2, col.axis = rgb(68, 84, 106, max=255),labels= c(1989:2018))
We make the two fits, and you use predict to get the y values
fit1=lm(land_area ~ Year_no, data = subset(dif2, int==0))
fit2=lm(land_area ~ Year_no, data = subset(dif2, int==1))
lines(1:10,predict(fit1,data.frame(Year_no=1:10)),lty=8,col="blue")
lines(12:23,predict(fit1,data.frame(Year_no=12:23)),lty=8,col="blue")
lines(26:30,predict(fit2,data.frame(Year_no=26:30)),lty=8,col="blue")

Is there a way to combine mosaic plots using different data sets so that they are outputted next to each other?

I am trying to combine 20 mosaic plots onto one output. par(mfrow=...) is not working. I would like the rows to have 3 plots in each row.
Here is code for just 4 of the plots that I am using:
library(vcd)
library(vcdExtra)
library(MASS)
All <- matrix(c(599,250,39,24, 157,238,89,40, 26,51,51,45, 26,26,30,57), 4, 4)
dimnames(All) <- list("2002" =c("Never","Light","Moderate","Heavy"), "2014" =c("Never","Light","Moderate","Heavy"))
All <- as.table(All)
Poor <- matrix(c(184,57,7,6, 51,43,12,6, 9,10,6,6, 9,5,9,11), 4, 4)
dimnames(Poor) <- list("2002"=c("Never","Light","Moderate","Heavy"), "2014" =c("Never","Light","Moderate","Heavy"))
Poor <- as.table(Poor)
NonPoor <- matrix(c(376,180,30,18, 94,192,77,34, 12,40,43,39, 15,19,21,41), 4, 4)
dimnames(NonPoor) <- list("2002"=c("Never","Light","Moderate","Heavy"), "2014" =c("Never","Light","Moderate","Heavy"))
NonPoor <- as.table(NonPoor)
Black <- matrix(c(239,82,7,6, 54,56,15,9, 8,12,9,5, 12,11,8,8), 4, 4)
dimnames(Black) <- list("2002"=c("Never","Light","Moderate","Heavy"), "2014" =c("Never","Light","Moderate","Heavy"))
Black <- as.table(Black)
mosaic(All, shade = TRUE, rot_labels = c(top = 90, left=0),just_labels = c("left","right","right","right"),offset_labels = c(-.4, 0, 0, 0),offset_varnames = c(1.5, 0, 0, 1.5))
mosaic(Poor, shade = TRUE, rot_labels = c(top = 90, left=0),just_labels = c("left","right","right","right"),offset_labels = c(-.4, 0, 0, 0),offset_varnames = c(1.5, 0, 0, 1.5))
mosaic(NonPoor, shade = TRUE, rot_labels = c(top = 90, left=0),just_labels = c("left","right","right","right"),offset_labels = c(-.4, 0, 0, 0),offset_varnames = c(1.5, 0, 0, 1.5))
mosaic(Black, shade = TRUE, rot_labels = c(top = 90, left=0),just_labels = c("left","right","right","right"),offset_labels = c(-.4, 0, 0, 0),offset_varnames = c(1.5, 0, 0, 1.5))
I did something similar earlier with bar plots and it worked just using the par(mfrow=...). Thank you in advance!
Its a little bit tricky with VCD graphics
try this approach
library(gridExtra)
fig1<-grid.grabExpr(mosaic(All, shade = TRUE, rot_labels = c(top = 90, left=0),just_labels = c("left","right","right","right"),offset_labels = c(-.4, 0, 0, 0),offset_varnames = c(1.5, 0, 0, 1.5)))
fig2<-grid.grabExpr(mosaic(Poor, shade = TRUE, rot_labels = c(top = 90, left=0),just_labels = c("left","right","right","right"),offset_labels = c(-.4, 0, 0, 0),offset_varnames = c(1.5, 0, 0, 1.5)))
fig3<-grid.grabExpr(mosaic(NonPoor, shade = TRUE, rot_labels = c(top = 90, left=0),just_labels = c("left","right","right","right"),offset_labels = c(-.4, 0, 0, 0),offset_varnames = c(1.5, 0, 0, 1.5)))
fig4<-grid.grabExpr(mosaic(Black, shade = TRUE, rot_labels = c(top = 90, left=0),just_labels = c("left","right","right","right"),offset_labels = c(-.4, 0, 0, 0),offset_varnames = c(1.5, 0, 0, 1.5)))
grid.arrange(fig1,fig2,fig3,fig4)

How to get a "Radial histogram" using R ggplot2 like this?

Which function in R ggplot2 should I use to get this graph?
Here, the number "2" and "6" is about the number of cells that have different Division angle.
This might be a better answer. It's possible to do it using base graphics too but may need more work. Here's an example.
d <- structure(list(Angle = c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90,
100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220,
230, 240, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 250
), Frequency = c(0, 0, 0.001, 2, 4, 18.03, 11, 12, 5, 7, 10,
13, 2, 0.003, 0.01, 0, 1, 0.05, 2, 3, 3.7, 6, 0, 0, 0, 0, 0.2,
0.006, 0, 0, 0, 0, 0, 0, 0, 0)), .Names = c("Angle", "Frequency"
), row.names = c(NA, 36L), class = "data.frame")
d$radian = d$Angle*pi/180
d$x = d$Frequency*cos(d$radian)
d$y = d$Frequency*sin(d$radian)
m = max(d$x, d$y)
graphics.off()
windows(width = 6, height = 6)
plot(x = m,
y = m,
xlim = c(-m,m),
ylim = c(-m,m),
type = "n",
asp = 1,
axes = FALSE,
xlab = "",
ylab = "")
par(xpd = TRUE)
symbols (x =c(0,0,0,0,0), y = c(0,0,0,0,0), circles=c(3,6,9,12,15), fg = "grey",
add = TRUE, inches = FALSE, lty = 2)
lines(x = c(-15,15), y = c(0,0), lty = 2)
lines(x = c(0,0), y = c(-15,15), lty = 2)
text(x = c(0,0,-15,15), y = c(-15,15,0,0),
labels = c("180","0","270","90"), pos = c(1,3,2,4))
for (i in 1:nrow(d)){
lines(x = c(0,d$x[i]), y = c(0,d$y[i]), lwd = 3)
}
NOTE: I screwed up when labeling angles

How to plot a Radar chart in ggplot2 or R [duplicate]

This question already has answers here:
creating "radar chart" (a.k.a. star plot; spider plot) using ggplot2 in R
(5 answers)
Closed 7 years ago.
I am trying to make a Radar plot as in attached image using and ggplot2 ( or any other package in R).This talk about this but my case is different as i am trying to create a spider plot for response data with certain range.
I made a plot using a code as below, but i couldn't figure out howto make this like in the image. Kindly help me with this.
Impcts <- c("system","supply","security","well-being")
present <- c(5,5,3,5)
past <- c(6,6,4,5)
group.names <- c("present", "past")
ddf.pre <- data.frame(matrix(c(rep(group.names[1], 4), Impcts), nrow = 4, ncol = 2), var.order = seq(1:4), value = present)
ddf.pas <- data.frame(matrix(c(rep(group.names[2], 4), Impcts), nrow = 4, ncol = 2), var.order = seq(1:4), value = past)
ddf <- rbind(ddf.pre, ddf.pas)
colnames(ddf) <- c("Group", "Impcts", "var.order", "var.value")
library(ggplot2)
ggplot(ddf, aes(y = var.value, x = reorder(Impcts, var.order),
group = Group, colour = Group))+
coord_polar() +
geom_path() +
geom_point()+
labs(title = "Impacts Analysis").
Here is my attempt.First I drew squares using geom_path(). Then, I drew two polygons on top of the squares using geom_polygon(). Finally I added annotations.
### Draw squares
mydf <- data.frame(id = rep(1:6, each = 5),
x = c(0, 6, 0, -6, 0,
0, 5, 0, -5, 0,
0, 4, 0, -4, 0,
0, 3, 0, -3, 0,
0, 2, 0, -2, 0,
0, 1, 0, -1, 0),
y = c(6, 0, -6, 0, 6,
5, 0, -5, 0, 5,
4, 0, -4, 0, 4,
3, 0, -3, 0, 3,
2, 0, -2, 0, 2,
1, 0, -1, 0, 1))
g <- ggplot(data = mydf, aes(x = x, y = y, group = factor(id)) +
geom_path()
### Draw polygons
mydf2 <- data.frame(id = rep(7:8, each = 5),
x = c(0, 6, 0, -5, 0,
0, 5, 0, -5, 0),
y = c(6, 0, -4, 0, 6,
5, 0, -3, 0, 5))
gg <- g +
geom_polygon(data = mydf2, aes(x = x, y = y, group = factor(id), fill = factor(id))) +
scale_fill_manual(name = "Time", values = c("darkolivegreen4", "brown4"),
labels = c("Past", "Present"))
### Add annotation
mydf3 <- data.frame(x = c(0, 6.5, 0, -6.5),
y = c(6.5, 0, -6.5, 0),
label = c("system", "supply", "security", "well-being"))
ggg <- gg +
annotate("text", x = mydf3$x, y = mydf3$y, label = mydf3$label, size = 3)
ggsave(ggg, file = "name.png", width = 10, height = 9)

Resources