So I have the following MWE, a horizontal line expresses the mean of a particular day and the points are measurements of emotion.
I'd like to draw a line instead of points within a day between the points, but the line must have breaks between days. I can't seem to figure out how to do this.
I tried the example on this page, but that does not seem to work for my data.
A friend of mine managed to do this for the horizontal lines (they have spaces between days), but I can't seem to change my code to let it work for my measurements within days.
MWE:
beeps.MWE <- c(91.188697, 87.846194, 93.166418, 96.249094, 95.495146, 99.362597, 94.373646,
81.995712, 87.626009, 91.880172, 93.112647, 99.349234, 87.073372, 85.161982, 88.119728,
89.738318, 68.891181, 62.504569, 75.131526, 56.035989, 66.035109, 56.012537)
day.MWE <- rep(c(91.35869, 63.17620), each = 11)
loc.MWE <- c(8, 15)
plot(day.MWE, type = "n", pch = 15, cex = 1.5, ylim = c(40, 110), bty = "n",
ylab = "score on PA/NA", xlab = "days of person i", axes = FALSE)
dayUn <- unique(day.MWE)
for (i in seq_along(dayUn))
{
points(which(day.MWE==dayUn[i]),day.MWE[day.MWE==dayUn[i]], type = 'l', lwd = "2")
}
points(1:length(beeps.MWE), beeps.MWE, type = "p")
lines(1:length(beeps.MWE), rep(mean(day.MWE), 22), lwd = "2", lty = 2)
axis(1, at = c(1, 20), labels = c("day 1", "day 2"))
axis(2, las = 1)
This is the output of the above code:
You're nearly there with the code provided. Just add a line to the loop to draw the lines between the points:
for (i in seq_along(dayUn)){
# draw horizontal lines to show the mean per day
points(which(day.MWE==dayUn[i]),day.MWE[day.MWE==dayUn[i]], type = 'l', lwd = "2")
# draw a line that connects points within a day
points(which(day.MWE==dayUn[i]),beeps.MWE[day.MWE==dayUn[i]], lwd = "2", type='l')
}
Also note that points(x,y,type='l') is the same as lines(x,y). Makes more sense ;)
Related
I am doing quarterly analysis, for which I want to plot a graph. To maintain continuity on x axis I have turned quarters into factors. But then when I am using plot function and trying to color it red, the col argument is not working.
An example:
quarterly_analysis <- data.frame(Quarter = as.factor(c(2020.1,2020.2,2020.3,2020.4,2021.1,2021.2,2021.3,2021.4)),
AvgDefault = as.numeric(c(0.24,0.27,0.17,0.35,0.32,0.42,0.38,0.40)))
plot(quarterly_analysis, col="red")
But I am getting the graph in black color as shown below:
Converting it to a factor is not ideal to plot unless you have multiple values for each factor - it tries to plot a box plot-style plot. For example, with 10 observations in the same factor, the col = "red" color shows up as the fill:
set.seed(123)
fact_example <- data.frame(factvar = as.factor(rep(LETTERS[1:3], 10)),
numvar = runif(30))
plot(fact_example$factvar, fact_example$numvar,
col = "red")
With only one observation for each factor, this is not ideal because it is just showing you the line that the box plot would make.
You could use border = "red:
plot(quarterly_analysis$Quarter,
quarterly_analysis$AvgDefault, border="red")
Or if you want more flexibility, you can plot it numerically and do a little tweaking for more control (i.e., can change the pch, or make it a line graph):
# make numeric x values to plot
x_vals <- as.numeric(substr(quarterly_analysis$Quarter,1,4)) + rep(seq(0, 1, length.out = 4))
par(mfrow=c(1,3))
plot(x_vals,
quarterly_analysis$AvgDefault, col="red",
pch = 7, main = "Square Symbol", axes = FALSE)
axis(1, at = x_vals,
labels = quarterly_analysis$Quarter)
axis(2)
plot(x_vals,
quarterly_analysis$AvgDefault, col="red",
type = "l", main = "Line graph", axes = FALSE)
axis(1, at = x_vals,
labels = quarterly_analysis$Quarter)
axis(2)
plot(x_vals,
quarterly_analysis$AvgDefault, col="red",
type = "b", pch = 7, main = "Both", axes = FALSE)
axis(1, at = x_vals,
labels = quarterly_analysis$Quarter)
axis(2)
Data
set.seed(123)
quarterly_analysis <- data.frame(Quarter = as.factor(paste0(2019:2022,
rep(c(".1", ".2", ".3", ".4"),
each = 4))),
AvgDefault = runif(16))
quarterly_analysis <- quarterly_analysis[order(quarterly_analysis$Quarter),]
I would like to draw three dotted lines all of them at the end of the existing line. This is my dataset and code:
x = data.frame(Debt = c(115.413 , 116.522 , 123.361, 129.021, 131.786, 131.557, 131.397, 131.355, 132.1, 134.77))
future = data.frame(144.9, 147.9, 150.9)
plot(x$Debt, lwd = 2, lty = 1, type = "l", ylab = "", xlab ="", col = "red", xaxt = "n")
lines(????)
axis(1, at = seq(2010, 2020, 1), labels = seq(2010, 2020, 1))
abline(v = 2019, col = "black", ldy = 3)
legend("bottomright", col = c("black", "blue", "green"), bty = "n", lty = 1)
An example of the plot I would like to get is:
In my case the lines that I want to draw from x$Debt are the points in future.
Can anyone help me?
This solution is not beautiful at all, but you can try this.
From your initial dataframes, x and future, create new dataframe combined two data, and slice the dataframe to show
The code is as follow:
x <- data.frame(Debt = c(115.413 , 116.522 , 123.361, 129.021, 131.786, 131.557, 131.397, 131.355, 132.1, 134.77))
future <- data.frame(Debt=c(144.9, 147.9, 150.9))
df <- data.frame(x=c(1:(nrow(x)+nrow(future))), y= c(x$Debt, future$Debt))
plot(range(df[,1]), range(100,150), type='n')
lines(df[1:nrow(x),1], df[1:nrow(x),2], type='l', col='black')
lines(df[nrow(x):nrow(df),1], df[nrow(x):nrow(df),2], type='l', col='blue')
If you want to multiple lines in future range, you can append the data with years and values to the df, and add lines() with proper slices.
I want to create a figure where for various reasons I need to specify the axis labels myself. But when I specify my labels (some have one digit, some two digits) R suppresses every other two-digit label because it decides there isn't enough room to show them all, but it leaves all of the one-digit labels, leaving the axis looking lopsided.
Is there a way to suppress labels consistently across the whole axis, based on whether any of them need to be skipped? Note: I have a lot of plots with varying scales, so I was looking for something I could use for all of them - I don't want to render all the labels for every plot, or to skip every other label in every plot. Suppressing labels will be desirable for some plots and not for others. I just want to skip every other label consistently, if that's what R chooses to do for the particular plot.
(Here is an example figure of what I mean. What I want is for the "6%" label to also be suppressed in the x axis.)
Example code:
library(labeling)
df <- data.frame("estimate" = c(9.81, 14.29, 12.94),
"lower" = c(4.54, 6.25, 5.12),
"upper" = c(12.85, 20.12, 15.84))
ticks <- extended(min(df$lower), max(df$upper), m = 5, only.loose = TRUE,
Q=c(2, 5, 10))
png("examplePlot.png", width = 1200, height = 900, pointsize = 10, res = 300)
bars <- barplot(df$estimate, horiz = TRUE, col = "white", border = NA,
xlim = c(min(ticks), max(ticks)), xaxt = "n", main = "Example")
arrows(df$lower, bars, df$upper, bars, code = 3, angle = 90, length = 0.03)
points(df$estimate, bars, pch = 20)
tickLabels <- paste(ticks, "%", sep = "")
axis(1, at=ticks, labels = tickLabels, cex.axis=1)
axis(2, at = bars, labels = c("c", "b", "a"), lwd = 0, las = 2)
dev.off()
This depends on the size of the plot, so you'll have to plot each label separately:
axis(1, lwd.ticks = 1, labels = FALSE, at = ticks) # plot line and ticks
i <- seq(1,length(ticks),2) # which labels to plot
for(ii in i)
axis(1, at = ticks[ii], labels = tickLabels[ii], cex.axis = 1, lwd = 0)
I know there are strong opinions about mixing plot types in the same figures, especially if there are two y axes involved. However, this is a situation in which I have no alternative - I need to create a figure using R that follows a standard format - a histogram on one axis (case counts), and a superimposed line graph showing an unrelated rate on an independent axis.
The best I have been able to do is stacked ggplot2 facets, but this is not as easy to interpret for the purposes of this analysis as the combined figure. The people reviewing this output will need it in the format they are used to.
I'm attaching an example below.
Any ideas?
For etiquette purposes, sample data below:
y1<-sample(0:1000,20,rep=TRUE)
y2<-sample(0:100,20,rep=TRUE)
x<-1981:2000
I feel your pain - have had to recreate plots before. even did it in SAS once
if it's a once off, I'm be tempted to go old-school. something like this:
# Generate some data
someData <- data.frame(Year = 1987:2009,
mCases = rpois(23, 3),
pVac = sample(55:80, 23, T))
par(mar = c(5, 5, 5, 5))
with(someData, {
# Generate the barplot
BP <- barplot(mCases, ylim = c(0, 18), names = Year,
yaxt = "n", xlab = "", ylab = "Measles cases in Thousands")
axis(side = 2, at = 2*1:9, las = 1)
box()
# Add the % Vaccinated
par(new = T)
plot(BP, pVac, type = "l", ylim = c(0, 100), axes = F, ylab = "", xlab = "")
axis(side = 4, las = 1)
nudge <- ifelse(pVac > median(pVac), 2, -2)
text(BP, pVac + nudge, pVac)
mtext(side = 4, "% Vaccinated", line = 3)
par(new = F)
})
Try library(plotrix)
library(plotrix)
## Create sample data
y2<-sample(0:80,20,rep=TRUE)
x2<-sort(sample(1980:2010,20,rep=F))
y1<-sample(0:18,20,rep=TRUE)
x1<-sort(sample(1980:2010,20,rep=F))
x<-1980:2010
twoord.plot(x1,y1,x2,y2,
lylim=c(0,18),rylim=c(0,100),type=c("bar","l"),
ylab="Measles Cases in thousands",rylab="% Vaccinated",
lytickpos=seq(0,18,by=2),rytickpos=seq(0,100,by=10),ylab.at=9,rylab.at=50,
lcol=3,rcol=4)
This question is related to a question I asked earlier.
So I've got some code with which I someone's overall mean emotion (dashed line), mean emotion per day (horizontal grey lines) and emotions measured per occasion (red line). I need to add a line that connect means per day. So in this case it means that I have to plot a line between the two grey lines. I have added a picture below in which the green line represents what kind of line I want to add.
MWE:
beeps.MWE <- c(91.188697, 87.846194, 93.166418, 96.249094, 95.495146, 99.362597, 94.373646,
81.995712, 87.626009, 91.880172, 93.112647, 99.349234, 87.073372, 85.161982, 88.119728,
89.738318, 68.891181, 62.504569, 75.131526, 56.035989, 66.035109, 56.012537)
day.MWE <- rep(c(91.35869, 63.17620), each = 11)
loc.MWE <- c(8, 15)
plot(day.MWE, type = "n", pch = 15, cex = 1.5, ylim = c(40, 110), bty = "n",
ylab = "score on PA/NA", xlab = "days of person i", axes = FALSE)
dayUn <- unique(day.MWE)
for (i in seq_along(dayUn))
{
lines(which(day.MWE==dayUn[i]),day.MWE[day.MWE==dayUn[i]], lwd = "2", col = "grey")
lines(which(day.MWE==dayUn[i]),day.MWE[day.MWE==dayUn[i]], lwd = "2")
}
lines(1:length(beeps.MWE), rep(mean(day.MWE), 22), lwd = "2", lty = 2)
axis(1, at = c(1, 20), labels = c("day 1", "day 2"))
axis(2, las = 1)
This is the output of the above code:
If you have an unknown (or large) number of days you can do it in several ways, but an easy way is to add
if(i>1){
lines(c(mean(which(day.MWE==dayUn[i-1])),mean(which(day.MWE==dayUn[i]))),dayUn[(i-1):i],col="green",lwd=5)
}
inside the for-loop. This will draw a line from day i-1 to day i for day i=2,3,....
You can do it the same way you add any other lines to a plot - with lines:
lines(c(mean(which(day.MWE==dayUn[1])),mean(which(day.MWE==dayUn[2]))),dayUn,col="green",lwd=5)