Change y-axis side when plotting factors - r

I have the following plot
k.factor<-factor(sample(1:5, 100, replace = T))
s.factor<-factor(sample(c("A", "B", "C"), 100, replace = T))
plot(k.factor, s.factor)
I would like to remove the left y-axis (A, B, C) and plot this information as a legend. How can I suppress this yaxis? I would also like the probability axis to be displayed as the left y axis (instead of right y axis as it is now)? How can I flip this?
Please base R answers only

If you don't mind using ggplot2 you could do it like this:
library(ggplot2)
ggplot(data.frame(k.factor, s.factor), aes(x = k.factor, fill = s.factor)) +
geom_bar(position="fill")

You can set axes=FALSE in your plotting statement and then manually add the axes using ?axis:
plot(k.factor, s.factor, axes=FALSE)
axis(1)
axis(2)
EDIT: In fact, you have to customize the axis statement.
# create offset and at variables
off <- 0.02
xat <- c(0, cumsum(prop.table(table(k.factor)) + off))
# plot
plot(k.factor, s.factor)
plot(k.factor, s.factor, axes=FALSE, off=100*off)
axis(1, at = (xat[-length(xat)] + xat[-1] - off)/2,
labels = 1:5, tick = FALSE)
axis(2)
You can also look at ?spineplot for more information about the argument off.

Related

R bar plot: how to set specified number in y axis but do not change the distance between numbers in R

I want to customized the y axis to a certain number, but the distance in the y axis should not be changed accordingly like below figure. I tried different way, but failed. Basically, when I use the axis(2, yseries), the y range will be changed.
The core I tried is like this:
yseries <- c(10,
20,
40,
80,
160,
320,
640,
1280)
gm <- c(760, 640)
barplot(gm, xaxt = "n", yaxt = "n")
# Y-axis
axis(2, at = yseries)
You can see the y axis is different from the attached figure (where the y ranges from 10 to 1280, but the distance in the y axis is not changed in this figure. I also want to make this kind of figure). Can you help me to figure out?
Thanks,
This is the figure I want to replicate it in y axis
You can set the range of the y axis in the plot command, and use a log scale to get equal distances between multiples as follows:
barplot(gm, xaxt = "n", yaxt = "n", log="y", ylim = range(yseries))
axis(2, at = yseries,las=1)
As requested in the comments - a ggplot2 solution. This is a little tricky because using bar plots with log-scales isn't very natural. The 'zero' disappears on the log-scale, so trying to set the limits within the scale function makes the columns disappear. I use coord_cartesian to set the limits instead (data is different to previous plot):
ggplot(df, aes(x, y)) +
geom_col() +
scale_y_log10(breaks=yseries)+
coord_cartesian(ylim=range(yseries))

How to add a vertical abline to the legend or write something on it in line plot in R?

I've added an verticle line at some point on x-axis (as shown in line plot of below Fig.) using abline() function in R, and I want to either put a legend for it or add some text over it (vertically on the abline).
So, is it possible to do this? If yes, then how I can do this?
Use text with the indicated arguments. Alternately use the legend function as shown.
abline is classic graphics so it is assumed you want to use that plotting system but if you want ggplot2 see Add a horizontal line to plot and legend in ggplot2 and make the obvious modifications to change the horizontal line to vertical.
x <- y <- 1:10; v <- 5 # input
plot(x, y)
abline(v = v, col = "red")
text("Vertical Line", x = v, y = max(y), srt = -90, pos = 4) # near top
text("Vertical Line", x = v, y = min(y), srt = 90, adj = c(0, -0.5)) # near bottom
legend("topleft", legend = "Vertical Line", pch = "|", col = "red")

Rotate x-axis labels at a given degree for boxplot in R

I generate a boxplot with code below:
boxplot(top10threads$affect ~ top10threads$ThreadID[], data = top10threads, xlab = "10 biggest Threads", ylab = "Affect", col=(c("gold","darkgreen")), srt=45)
But as you may notice that some labels in x-axis are missing, so I want to rotate them into 45 degrees. I added srt=45, but it doesn't work.
By setting las=2 can rotate them vertically, but it's not exactly I need.
How could I do that? Thanks.
First, store the output of boxplot() as a object. It contains names of the groups. You can use $names to get them. Then use text() to add labels on the axis. The argument srt works on text().
bp <- boxplot(y ~ x, data = df, col = c("gold", "darkgreen"), xaxt = "n")
tick <- seq_along(bp$names)
axis(1, at = tick, labels = FALSE)
text(tick, par("usr")[3] - 0.3, bp$names, srt = 45, xpd = TRUE)
Data
df <- data.frame(x = sample(100:110, 100, TRUE), y = rnorm(100))
Some test data:
mydata=lapply(1:5,function(i) rnorm(100,mean=i))
names(mydata)=c("first","second","third","fourth","fifth")
First, plot the boxplot with no x-axis:
boxplot(mydata,xaxt="n",xlab="")
Then, we make a function to add textual x-axis labels:
x_axis_labels=function(labels,every_nth=1,...) {
axis(side=1,at=seq_along(labels),labels=F)
text(x=(seq_along(labels))[seq_len(every_nth)==1],
y=par("usr")[3]-0.075*(par("usr")[4]-par("usr")[3]),
labels=labels[seq_len(every_nth)==1],xpd=TRUE,...)
}
# axis() draws the axis with ticks at positions specified by at. Again, we don't plot the labels yet.
# text() plots the labels at positions given by x and y.
# We estimate the y-positions from the values of the y-axis (using par("usr")),
# and specify xpd=TRUE to indicate that we don't want to crop plotting to within the plot area
# Note that we select the [seq_len(every_nth)==1] elements of both the x positions and the labels,
# so we can easily skip labels if there would be too many to cram in otherwise.
# Finally, we leave a ... in the function so we can pass additional arguments to text()
Finally, we call the new function to plot the axis tick labels:
x_axis_labels(labels=names(mydata),every_nth=1,adj=1,srt=45)
Here we take advantage of the ... in the function to pass the rotation/justification parameters: adj=1 specifies to right-justify the text labels, and srt=45 indicates to rotate them by 45 degrees.

R: how to optimize the position of labeling in plot

Hi I guess that I have quite a rudimentary question here.
I have a plot like this
but as you could easily notice, some of the label could not be displayed (some are overlapped with the symbols, some are just out of the figure frame)
I noticed that there are some way to adjust the position of labels
text(tsne_out$Y[,1], tsne_out$Y[,2], labels=samplegrouptry, pos=1)
for example, I could specify the the value of "pos" (from 1 to 4). I guess they are good enough in most cases .But I wonder whether there are some better ways to do that.
Any suggestion, thanks!
Following the suggestion from
vas_u Through change the axis ranges as well as "pos", I could get better plot:
One way around the problem would be to enlarge the axes of the plot.
Your example approximately reproduced with dummy data:
x <- rnorm(16, mean = 0)
y <- rnorm(16, mean = 1)
# Initial scatterplot with text labels out of plot area:
plot(x, y, pch = 16)
text(x, y, labels = paste("Name", 1:16), pos = 1) # Some labels outside plot area
# Second plot with the X and Y axes gently expanded:
plot(x, y, pch = 16,
xlim = 1.1*range(x),
ylim = 1.1*range(y))
text(x, y, labels = paste("Name", 1:16), pos = 1) # Labels now fit inside!
I hope this helps.

How to plot the value of abline in R?

I used this code to make this plot:
plot(p, cv2,col=rgb(0,100,0,50,maxColorValue=255),pch=16,
panel.last=abline(h=67,v=1.89, lty=1,lwd=3))
My plot looks like this:
1.) How can I plot the value of the ablines in a simple plot?
2.) How can I scale my plot so that both lines appear in the middle?
to change scale of plot so lines are in the middle change the axes i.e.
x<-1:10
y<-1:10
plot(x,y)
abline(a=1,b=0,v=1)
changed to:
x<-1:10
y<-1:10
plot(x,y,xlim=c(-30,30))
abline(a=1,b=0,v=1)
by "value" I am assuming you mean where the line cuts the x-axis? Something like text? i.e.:
text((0), min(y), "number", pos=2)
if you want the label on the x axis then try:
abline(a=1,b=0,v=1)
axis(1, at=1,labels=1)
to prevent overlap between labels you could remove the zero i.e.:
plot(x,y,xlim=c(-30,30),yaxt="n")
axis(2, at=c(1.77,5,10,15,20,25))
or before you plot extend the margins and add the labels further from the axis
par(mar = c(6.5, 6.5, 6.5, 6.5))
plot(x,y,xlim=c(-30,30))
abline(a=1,b=0,v=1)
axis(2, at=1.77,labels=1.77,mgp = c(10, 2, 0))
Similar in spirit to the answer proposed by #user1317221, here is my suggestion
# generate some fake points
x <- rnorm(100)
y <- rnorm(100)
# positions of the lines
vert = 0.5
horiz = 1.3
To display the lines at the center of the plot, first compute the horizontal and vertical distances between the data points and the lines, then adjust the limits adequately.
# compute the limits, in order for the lines to be centered
# REM we add a small fraction (here 10%) to leave some empty space,
# available to plot the values inside the frame (useful for one the solutions, see below)
xlim = vert + c(-1.1, 1.1) * max(abs(x-vert))
ylim = horiz + c(-1.1, 1.1) * max(abs(y-horiz))
# do the main plotting
plot(x, y, xlim=xlim, ylim=ylim)
abline(h=horiz, v=vert)
Now, you could plot the 'values of the lines', either on the axes (the lineparameter allows you to control for possible overlapping):
mtext(c(vert, horiz), side=c(1,2))
or alternatively within the plotting frame:
text(x=vert, y=ylim[1], labels=vert, adj=c(1.1,1), col='blue')
text(x=xlim[1], y=horiz, labels=horiz, adj=c(0.9,-0.1), col='blue')
HTH

Resources