Plot ribbon between lines created with geom_abline2019 Community Moderator ElectionPlot two graphs in same plot in Rr - ggplot2 - create a shaded region between two geom_abline layersA better way to build confidence bands around mean/median of an observed sample using ggplot2How can I color region between two lines specified by slope and intercept on a ggplot R in a log scalegeom_abline for logistic regression (ggplot2)ggplot2: fill color behaviour of geom_ribbonAdding a ribbon when faceting in ggplot2ggplot2 manually adjust linetype of main plot but remove outline of geom_ribbonHow do I shade between lines with identical “y”s?Shade area between two lines defined with function in ggplot
Book about a time-travel war fought by computers
Being asked to review a paper in conference one has submitted to
School performs periodic password audits. Is my password compromised?
Reason why dimensional travelling would be restricted
PTIJ: Aharon, King of Egypt
Giving a talk in my old university, how prominently should I tell students my salary?
How do you say “my friend is throwing a party, do you wanna come?” in german
In which way proportional valves are controlled solely by current?
Should I use HTTPS on a domain that will only be used for redirection?
PTIJ: What’s wrong with eating meat and couscous?
Why is it "take a leak?"
How can I handle a player who pre-plans arguments about my rulings on RAW?
How do I deal with being envious of my own players?
Draw bounding region by list of points
Difference between 'stomach' and 'uterus'
Sometimes a banana is just a banana
The need of reserving one's ability in job interviews
3.5% Interest Student Loan or use all of my savings on Tuition?
Rationale to prefer local variables over instance variables?
Can we carry rice to Japan?
Is there a full canon version of Tyrion's jackass/honeycomb joke?
Can a space-faring robot still function over a billion years?
Is there a math equivalent to the conditional ternary operator?
Why is my Contribution Detail Report (native CiviCRM Core report) not accurate?
Plot ribbon between lines created with geom_abline
2019 Community Moderator ElectionPlot two graphs in same plot in Rr - ggplot2 - create a shaded region between two geom_abline layersA better way to build confidence bands around mean/median of an observed sample using ggplot2How can I color region between two lines specified by slope and intercept on a ggplot R in a log scalegeom_abline for logistic regression (ggplot2)ggplot2: fill color behaviour of geom_ribbonAdding a ribbon when faceting in ggplot2ggplot2 manually adjust linetype of main plot but remove outline of geom_ribbonHow do I shade between lines with identical “y”s?Shade area between two lines defined with function in ggplot
I am trying to create a shaded area between lines created with geom_abline
require(ggplot2)
val_intcpt <- c(-1,1)
ggplot() +
geom_point(data = iris, mapping = aes(x = Petal.Length, y = Sepal.Width)) +
geom_abline(intercept = 0, slope = 1, linetype = 'dashed') +
geom_abline(intercept = val_intcpt, slope = 1, linetype = 'dotted')
The idea would be to shade the area between the dotted lines.
geom_ribbon
doesn't work because it requiresymin/ymax
and I do not have this information (of course, I could just hardcode a data frame, but this is not exactly a great solution, as it would not work automatically for any given data.)- Using
ggplot_build
doesn't help because the data frames do not provide x/y data.
I am sure I am missing something very obvious:(
r ggplot2
add a comment |
I am trying to create a shaded area between lines created with geom_abline
require(ggplot2)
val_intcpt <- c(-1,1)
ggplot() +
geom_point(data = iris, mapping = aes(x = Petal.Length, y = Sepal.Width)) +
geom_abline(intercept = 0, slope = 1, linetype = 'dashed') +
geom_abline(intercept = val_intcpt, slope = 1, linetype = 'dotted')
The idea would be to shade the area between the dotted lines.
geom_ribbon
doesn't work because it requiresymin/ymax
and I do not have this information (of course, I could just hardcode a data frame, but this is not exactly a great solution, as it would not work automatically for any given data.)- Using
ggplot_build
doesn't help because the data frames do not provide x/y data.
I am sure I am missing something very obvious:(
r ggplot2
add a comment |
I am trying to create a shaded area between lines created with geom_abline
require(ggplot2)
val_intcpt <- c(-1,1)
ggplot() +
geom_point(data = iris, mapping = aes(x = Petal.Length, y = Sepal.Width)) +
geom_abline(intercept = 0, slope = 1, linetype = 'dashed') +
geom_abline(intercept = val_intcpt, slope = 1, linetype = 'dotted')
The idea would be to shade the area between the dotted lines.
geom_ribbon
doesn't work because it requiresymin/ymax
and I do not have this information (of course, I could just hardcode a data frame, but this is not exactly a great solution, as it would not work automatically for any given data.)- Using
ggplot_build
doesn't help because the data frames do not provide x/y data.
I am sure I am missing something very obvious:(
r ggplot2
I am trying to create a shaded area between lines created with geom_abline
require(ggplot2)
val_intcpt <- c(-1,1)
ggplot() +
geom_point(data = iris, mapping = aes(x = Petal.Length, y = Sepal.Width)) +
geom_abline(intercept = 0, slope = 1, linetype = 'dashed') +
geom_abline(intercept = val_intcpt, slope = 1, linetype = 'dotted')
The idea would be to shade the area between the dotted lines.
geom_ribbon
doesn't work because it requiresymin/ymax
and I do not have this information (of course, I could just hardcode a data frame, but this is not exactly a great solution, as it would not work automatically for any given data.)- Using
ggplot_build
doesn't help because the data frames do not provide x/y data.
I am sure I am missing something very obvious:(
r ggplot2
r ggplot2
asked Oct 22 '18 at 14:55
TjeboTjebo
2,5251529
2,5251529
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Plot a polygon, perhaps?
# let ss be the slope for geom_abline
ss <- 1
p <- ggplot() +
geom_point(data = iris, mapping = aes(x = Petal.Length, y = Sepal.Width)) +
geom_abline(intercept = 0, slope = ss, linetype = 'dashed') +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dotted')
# get plot limits
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
# create polygon coordinates, setting x positions somewhere
# beyond the current plot limits
df <- data.frame(
x = rep(c(p.x[1] - (p.x[2] - p.x[1]),
p.x[2] + (p.x[2] - p.x[1])), each = 2),
intcpt = c(val_intcpt, rev(val_intcpt))
) %>%
mutate(y = intcpt + ss * x)
# add polygon layer, & constrain to previous plot limits
p +
annotate(geom = "polygon",
x = df$x,
y = df$y,
alpha = 0.2) +
coord_cartesian(xlim = p.x, ylim = p.y)
Explanation for why it works
Let's consider a normal plot:
ss <- 0.75 # this doubles up as illustration for different slope values
p <- ggplot() +
geom_point(data = iris, aes(x = Petal.Length, y = Sepal.Width), color = "grey75") +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dashed',
color = c("blue", "red"), size = 1) +
annotate(geom = "text", x = c(6, 3), y = c(2.3, 4), color = c("blue", "red"), size = 4,
label = c("y == a[1] + b*x", "y == a[2] + b*x"), parse = TRUE)
coord_fixed(ratio = 1.5) +
theme_classic()
p + ggtitle("Step 0: Construct plot")
Get the limits p.x
/ p.y
from the p
, & take a look at the corresponding locations in the plot itself (in purple):
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
p1 <- p +
geom_point(data = data.frame(x = p.x, y = p.y) %>% tidyr::complete(x, y),
aes(x = x, y = y),
size = 2, stroke = 1, color = "purple")
p1 + ggtitle("Step 1: Get plot limits")
Take note of the values for the x-axis limits (still in purple):
p2 <- p1 +
annotate(geom = "text", x = p.x, y = min(p.y), label = c("x[0]", "x[1]"),
vjust = -1, parse = TRUE, color = "purple", size = 4)
p2 +
ggtitle("Step 2: Note x-axis coordinates of limits") +
annotate(geom = "segment",
x = p.x[1] + diff(p.x),
xend = p.x[2] - diff(p.x),
y = min(p.y), yend = min(p.y),
color = "purple", linetype = "dashed", size = 1,
arrow = arrow(ends = "both")) +
annotate(geom = "text", x = mean(p.x), y = min(p.y), label = "x[1] - x[0]",
vjust = -1, parse = TRUE, color = "purple", size = 4)
We want to construct a polygon (a parallelogram, to be precise) with corners far beyond the original plot's range, so that none of it is visible within the plot. One way to achieve this is to take the existing plot's x-axis limits & shifting them outwards by the same amount as the existing plot's x-axis range: the resulting positions (in black) are pretty far out:
p3 <- p2 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
shape = 4, size = 1, stroke = 2) +
annotate(geom = "text",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
label = c("x[0] - (x[1] - x[0])", "x[1] + (x[1] - x[0])"),
vjust = -1, parse = TRUE, size = 5, hjust = c(0, 1))
p3 +
ggtitle("Calculate x-axis coordinates of two points far beyond the limits") +
annotate(geom = "segment",
x = p.x,
xend = p.x + c(-diff(p.x), diff(p.x)),
y = min(p.y), yend = min(p.y),
linetype = "dashed", size = 0.5,
arrow = arrow(ends = "both", length = unit(0.1, "inches")))
We can derive the corresponding y values associated with the x-axis positions, for each geom_abline
(in red / blue), using the standard y = a + b * x
formula:
p4 <- p3 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[2] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "red") +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[1] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "blue")
p4 +
ggtitle("Calculate the corresponding y coordinates for both ab-lines") +
annotate(geom = "text",
x = p.x[1] - diff(p.x),
y = val_intcpt + ss * (p.x[1] - diff(p.x)),
label = c("y == a[1] + b * (x[0] - (x[1] - x[0]))",
"y == a[2] + b * (x[0] - (x[1] - x[0]))"),
hjust = -0.2, parse = TRUE,
color = c("blue", "red")) +
annotate(geom = "text",
x = p.x[2] + diff(p.x),
y = val_intcpt + ss * (p.x[2] + diff(p.x)),
label = c("y == a[1] + b * (x[1] + (x[1] - x[0]))",
"y == a[2] + b * (x[1] + (x[1] - x[0]))"),
hjust = 1.2, parse = TRUE,
color = c("blue", "red"))
Now that we have the x / y coordinates for the corners, constructing the polygon is a simple matter of joining them together:
p5 <- p4 +
annotate(geom = "polygon",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
fill = "yellow", alpha = 0.4)
p5 +
ggtitle("Step 5: Draw polygon based on calculated coordinates") +
annotate(geom = "label",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
label = c("list(x[0] - (x[1] - x[0]), a[1] + b*(x[0] - (x[1] - x[0])))",
"list(x[0] - (x[1] - x[0]), a[2] + b*(x[0] - (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[2] + b*(x[1] + (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[1] + b*(x[1] + (x[1] - x[0])))"),
parse = TRUE, hjust = rep(c(0, 1), each = 2))
Apply the original plot range, & we have a polygon pretending to be a filled ribbon, with corners safely hidden out of the way beyond view:
p5 +
ggtitle("Step 6: Reset plot range to original range") +
coord_fixed(ratio = 1.5, xlim = p.x, ylim = p.y)
(Note: There's a lot of unnecessary code here, to label & colour intermediate steps for illustration purpose. For actual use, as per my original solution, none of that is necessary. But as far as explanation goes, it's either this or sketch + scan in my crappy handwriting...)
yeah That is a nice hack :) I didn't knowlayer_scales
. Again, I learned a lot from you :) I will wait a tiny bit with accepting the answer though, there might be other suggestions out there
– Tjebo
Oct 22 '18 at 15:40
The solution is great for my example (and also for my requirements) but would not work for different slopes. Do you suggest editing the question to make it more general or ask a new question? Happy to do both
– Tjebo
Oct 22 '18 at 15:53
(Sorry, I feel very stupid). I admit I just do not manage to understand why your solution works at all. Why does using the coordinates of the plot limits result in the correct polygon?? That is beyond my ken
– Tjebo
Oct 22 '18 at 16:02
1
@Tjebo I just saw your questions & now I feel really bad. >_< Will update my answer to incorporate different slopes.
– Z.Lin
17 hours ago
1
@Tjebo I've updated my answer.
– Z.Lin
15 hours ago
|
show 1 more comment
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52932253%2fplot-ribbon-between-lines-created-with-geom-abline%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Plot a polygon, perhaps?
# let ss be the slope for geom_abline
ss <- 1
p <- ggplot() +
geom_point(data = iris, mapping = aes(x = Petal.Length, y = Sepal.Width)) +
geom_abline(intercept = 0, slope = ss, linetype = 'dashed') +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dotted')
# get plot limits
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
# create polygon coordinates, setting x positions somewhere
# beyond the current plot limits
df <- data.frame(
x = rep(c(p.x[1] - (p.x[2] - p.x[1]),
p.x[2] + (p.x[2] - p.x[1])), each = 2),
intcpt = c(val_intcpt, rev(val_intcpt))
) %>%
mutate(y = intcpt + ss * x)
# add polygon layer, & constrain to previous plot limits
p +
annotate(geom = "polygon",
x = df$x,
y = df$y,
alpha = 0.2) +
coord_cartesian(xlim = p.x, ylim = p.y)
Explanation for why it works
Let's consider a normal plot:
ss <- 0.75 # this doubles up as illustration for different slope values
p <- ggplot() +
geom_point(data = iris, aes(x = Petal.Length, y = Sepal.Width), color = "grey75") +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dashed',
color = c("blue", "red"), size = 1) +
annotate(geom = "text", x = c(6, 3), y = c(2.3, 4), color = c("blue", "red"), size = 4,
label = c("y == a[1] + b*x", "y == a[2] + b*x"), parse = TRUE)
coord_fixed(ratio = 1.5) +
theme_classic()
p + ggtitle("Step 0: Construct plot")
Get the limits p.x
/ p.y
from the p
, & take a look at the corresponding locations in the plot itself (in purple):
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
p1 <- p +
geom_point(data = data.frame(x = p.x, y = p.y) %>% tidyr::complete(x, y),
aes(x = x, y = y),
size = 2, stroke = 1, color = "purple")
p1 + ggtitle("Step 1: Get plot limits")
Take note of the values for the x-axis limits (still in purple):
p2 <- p1 +
annotate(geom = "text", x = p.x, y = min(p.y), label = c("x[0]", "x[1]"),
vjust = -1, parse = TRUE, color = "purple", size = 4)
p2 +
ggtitle("Step 2: Note x-axis coordinates of limits") +
annotate(geom = "segment",
x = p.x[1] + diff(p.x),
xend = p.x[2] - diff(p.x),
y = min(p.y), yend = min(p.y),
color = "purple", linetype = "dashed", size = 1,
arrow = arrow(ends = "both")) +
annotate(geom = "text", x = mean(p.x), y = min(p.y), label = "x[1] - x[0]",
vjust = -1, parse = TRUE, color = "purple", size = 4)
We want to construct a polygon (a parallelogram, to be precise) with corners far beyond the original plot's range, so that none of it is visible within the plot. One way to achieve this is to take the existing plot's x-axis limits & shifting them outwards by the same amount as the existing plot's x-axis range: the resulting positions (in black) are pretty far out:
p3 <- p2 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
shape = 4, size = 1, stroke = 2) +
annotate(geom = "text",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
label = c("x[0] - (x[1] - x[0])", "x[1] + (x[1] - x[0])"),
vjust = -1, parse = TRUE, size = 5, hjust = c(0, 1))
p3 +
ggtitle("Calculate x-axis coordinates of two points far beyond the limits") +
annotate(geom = "segment",
x = p.x,
xend = p.x + c(-diff(p.x), diff(p.x)),
y = min(p.y), yend = min(p.y),
linetype = "dashed", size = 0.5,
arrow = arrow(ends = "both", length = unit(0.1, "inches")))
We can derive the corresponding y values associated with the x-axis positions, for each geom_abline
(in red / blue), using the standard y = a + b * x
formula:
p4 <- p3 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[2] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "red") +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[1] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "blue")
p4 +
ggtitle("Calculate the corresponding y coordinates for both ab-lines") +
annotate(geom = "text",
x = p.x[1] - diff(p.x),
y = val_intcpt + ss * (p.x[1] - diff(p.x)),
label = c("y == a[1] + b * (x[0] - (x[1] - x[0]))",
"y == a[2] + b * (x[0] - (x[1] - x[0]))"),
hjust = -0.2, parse = TRUE,
color = c("blue", "red")) +
annotate(geom = "text",
x = p.x[2] + diff(p.x),
y = val_intcpt + ss * (p.x[2] + diff(p.x)),
label = c("y == a[1] + b * (x[1] + (x[1] - x[0]))",
"y == a[2] + b * (x[1] + (x[1] - x[0]))"),
hjust = 1.2, parse = TRUE,
color = c("blue", "red"))
Now that we have the x / y coordinates for the corners, constructing the polygon is a simple matter of joining them together:
p5 <- p4 +
annotate(geom = "polygon",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
fill = "yellow", alpha = 0.4)
p5 +
ggtitle("Step 5: Draw polygon based on calculated coordinates") +
annotate(geom = "label",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
label = c("list(x[0] - (x[1] - x[0]), a[1] + b*(x[0] - (x[1] - x[0])))",
"list(x[0] - (x[1] - x[0]), a[2] + b*(x[0] - (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[2] + b*(x[1] + (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[1] + b*(x[1] + (x[1] - x[0])))"),
parse = TRUE, hjust = rep(c(0, 1), each = 2))
Apply the original plot range, & we have a polygon pretending to be a filled ribbon, with corners safely hidden out of the way beyond view:
p5 +
ggtitle("Step 6: Reset plot range to original range") +
coord_fixed(ratio = 1.5, xlim = p.x, ylim = p.y)
(Note: There's a lot of unnecessary code here, to label & colour intermediate steps for illustration purpose. For actual use, as per my original solution, none of that is necessary. But as far as explanation goes, it's either this or sketch + scan in my crappy handwriting...)
yeah That is a nice hack :) I didn't knowlayer_scales
. Again, I learned a lot from you :) I will wait a tiny bit with accepting the answer though, there might be other suggestions out there
– Tjebo
Oct 22 '18 at 15:40
The solution is great for my example (and also for my requirements) but would not work for different slopes. Do you suggest editing the question to make it more general or ask a new question? Happy to do both
– Tjebo
Oct 22 '18 at 15:53
(Sorry, I feel very stupid). I admit I just do not manage to understand why your solution works at all. Why does using the coordinates of the plot limits result in the correct polygon?? That is beyond my ken
– Tjebo
Oct 22 '18 at 16:02
1
@Tjebo I just saw your questions & now I feel really bad. >_< Will update my answer to incorporate different slopes.
– Z.Lin
17 hours ago
1
@Tjebo I've updated my answer.
– Z.Lin
15 hours ago
|
show 1 more comment
Plot a polygon, perhaps?
# let ss be the slope for geom_abline
ss <- 1
p <- ggplot() +
geom_point(data = iris, mapping = aes(x = Petal.Length, y = Sepal.Width)) +
geom_abline(intercept = 0, slope = ss, linetype = 'dashed') +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dotted')
# get plot limits
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
# create polygon coordinates, setting x positions somewhere
# beyond the current plot limits
df <- data.frame(
x = rep(c(p.x[1] - (p.x[2] - p.x[1]),
p.x[2] + (p.x[2] - p.x[1])), each = 2),
intcpt = c(val_intcpt, rev(val_intcpt))
) %>%
mutate(y = intcpt + ss * x)
# add polygon layer, & constrain to previous plot limits
p +
annotate(geom = "polygon",
x = df$x,
y = df$y,
alpha = 0.2) +
coord_cartesian(xlim = p.x, ylim = p.y)
Explanation for why it works
Let's consider a normal plot:
ss <- 0.75 # this doubles up as illustration for different slope values
p <- ggplot() +
geom_point(data = iris, aes(x = Petal.Length, y = Sepal.Width), color = "grey75") +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dashed',
color = c("blue", "red"), size = 1) +
annotate(geom = "text", x = c(6, 3), y = c(2.3, 4), color = c("blue", "red"), size = 4,
label = c("y == a[1] + b*x", "y == a[2] + b*x"), parse = TRUE)
coord_fixed(ratio = 1.5) +
theme_classic()
p + ggtitle("Step 0: Construct plot")
Get the limits p.x
/ p.y
from the p
, & take a look at the corresponding locations in the plot itself (in purple):
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
p1 <- p +
geom_point(data = data.frame(x = p.x, y = p.y) %>% tidyr::complete(x, y),
aes(x = x, y = y),
size = 2, stroke = 1, color = "purple")
p1 + ggtitle("Step 1: Get plot limits")
Take note of the values for the x-axis limits (still in purple):
p2 <- p1 +
annotate(geom = "text", x = p.x, y = min(p.y), label = c("x[0]", "x[1]"),
vjust = -1, parse = TRUE, color = "purple", size = 4)
p2 +
ggtitle("Step 2: Note x-axis coordinates of limits") +
annotate(geom = "segment",
x = p.x[1] + diff(p.x),
xend = p.x[2] - diff(p.x),
y = min(p.y), yend = min(p.y),
color = "purple", linetype = "dashed", size = 1,
arrow = arrow(ends = "both")) +
annotate(geom = "text", x = mean(p.x), y = min(p.y), label = "x[1] - x[0]",
vjust = -1, parse = TRUE, color = "purple", size = 4)
We want to construct a polygon (a parallelogram, to be precise) with corners far beyond the original plot's range, so that none of it is visible within the plot. One way to achieve this is to take the existing plot's x-axis limits & shifting them outwards by the same amount as the existing plot's x-axis range: the resulting positions (in black) are pretty far out:
p3 <- p2 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
shape = 4, size = 1, stroke = 2) +
annotate(geom = "text",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
label = c("x[0] - (x[1] - x[0])", "x[1] + (x[1] - x[0])"),
vjust = -1, parse = TRUE, size = 5, hjust = c(0, 1))
p3 +
ggtitle("Calculate x-axis coordinates of two points far beyond the limits") +
annotate(geom = "segment",
x = p.x,
xend = p.x + c(-diff(p.x), diff(p.x)),
y = min(p.y), yend = min(p.y),
linetype = "dashed", size = 0.5,
arrow = arrow(ends = "both", length = unit(0.1, "inches")))
We can derive the corresponding y values associated with the x-axis positions, for each geom_abline
(in red / blue), using the standard y = a + b * x
formula:
p4 <- p3 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[2] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "red") +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[1] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "blue")
p4 +
ggtitle("Calculate the corresponding y coordinates for both ab-lines") +
annotate(geom = "text",
x = p.x[1] - diff(p.x),
y = val_intcpt + ss * (p.x[1] - diff(p.x)),
label = c("y == a[1] + b * (x[0] - (x[1] - x[0]))",
"y == a[2] + b * (x[0] - (x[1] - x[0]))"),
hjust = -0.2, parse = TRUE,
color = c("blue", "red")) +
annotate(geom = "text",
x = p.x[2] + diff(p.x),
y = val_intcpt + ss * (p.x[2] + diff(p.x)),
label = c("y == a[1] + b * (x[1] + (x[1] - x[0]))",
"y == a[2] + b * (x[1] + (x[1] - x[0]))"),
hjust = 1.2, parse = TRUE,
color = c("blue", "red"))
Now that we have the x / y coordinates for the corners, constructing the polygon is a simple matter of joining them together:
p5 <- p4 +
annotate(geom = "polygon",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
fill = "yellow", alpha = 0.4)
p5 +
ggtitle("Step 5: Draw polygon based on calculated coordinates") +
annotate(geom = "label",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
label = c("list(x[0] - (x[1] - x[0]), a[1] + b*(x[0] - (x[1] - x[0])))",
"list(x[0] - (x[1] - x[0]), a[2] + b*(x[0] - (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[2] + b*(x[1] + (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[1] + b*(x[1] + (x[1] - x[0])))"),
parse = TRUE, hjust = rep(c(0, 1), each = 2))
Apply the original plot range, & we have a polygon pretending to be a filled ribbon, with corners safely hidden out of the way beyond view:
p5 +
ggtitle("Step 6: Reset plot range to original range") +
coord_fixed(ratio = 1.5, xlim = p.x, ylim = p.y)
(Note: There's a lot of unnecessary code here, to label & colour intermediate steps for illustration purpose. For actual use, as per my original solution, none of that is necessary. But as far as explanation goes, it's either this or sketch + scan in my crappy handwriting...)
yeah That is a nice hack :) I didn't knowlayer_scales
. Again, I learned a lot from you :) I will wait a tiny bit with accepting the answer though, there might be other suggestions out there
– Tjebo
Oct 22 '18 at 15:40
The solution is great for my example (and also for my requirements) but would not work for different slopes. Do you suggest editing the question to make it more general or ask a new question? Happy to do both
– Tjebo
Oct 22 '18 at 15:53
(Sorry, I feel very stupid). I admit I just do not manage to understand why your solution works at all. Why does using the coordinates of the plot limits result in the correct polygon?? That is beyond my ken
– Tjebo
Oct 22 '18 at 16:02
1
@Tjebo I just saw your questions & now I feel really bad. >_< Will update my answer to incorporate different slopes.
– Z.Lin
17 hours ago
1
@Tjebo I've updated my answer.
– Z.Lin
15 hours ago
|
show 1 more comment
Plot a polygon, perhaps?
# let ss be the slope for geom_abline
ss <- 1
p <- ggplot() +
geom_point(data = iris, mapping = aes(x = Petal.Length, y = Sepal.Width)) +
geom_abline(intercept = 0, slope = ss, linetype = 'dashed') +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dotted')
# get plot limits
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
# create polygon coordinates, setting x positions somewhere
# beyond the current plot limits
df <- data.frame(
x = rep(c(p.x[1] - (p.x[2] - p.x[1]),
p.x[2] + (p.x[2] - p.x[1])), each = 2),
intcpt = c(val_intcpt, rev(val_intcpt))
) %>%
mutate(y = intcpt + ss * x)
# add polygon layer, & constrain to previous plot limits
p +
annotate(geom = "polygon",
x = df$x,
y = df$y,
alpha = 0.2) +
coord_cartesian(xlim = p.x, ylim = p.y)
Explanation for why it works
Let's consider a normal plot:
ss <- 0.75 # this doubles up as illustration for different slope values
p <- ggplot() +
geom_point(data = iris, aes(x = Petal.Length, y = Sepal.Width), color = "grey75") +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dashed',
color = c("blue", "red"), size = 1) +
annotate(geom = "text", x = c(6, 3), y = c(2.3, 4), color = c("blue", "red"), size = 4,
label = c("y == a[1] + b*x", "y == a[2] + b*x"), parse = TRUE)
coord_fixed(ratio = 1.5) +
theme_classic()
p + ggtitle("Step 0: Construct plot")
Get the limits p.x
/ p.y
from the p
, & take a look at the corresponding locations in the plot itself (in purple):
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
p1 <- p +
geom_point(data = data.frame(x = p.x, y = p.y) %>% tidyr::complete(x, y),
aes(x = x, y = y),
size = 2, stroke = 1, color = "purple")
p1 + ggtitle("Step 1: Get plot limits")
Take note of the values for the x-axis limits (still in purple):
p2 <- p1 +
annotate(geom = "text", x = p.x, y = min(p.y), label = c("x[0]", "x[1]"),
vjust = -1, parse = TRUE, color = "purple", size = 4)
p2 +
ggtitle("Step 2: Note x-axis coordinates of limits") +
annotate(geom = "segment",
x = p.x[1] + diff(p.x),
xend = p.x[2] - diff(p.x),
y = min(p.y), yend = min(p.y),
color = "purple", linetype = "dashed", size = 1,
arrow = arrow(ends = "both")) +
annotate(geom = "text", x = mean(p.x), y = min(p.y), label = "x[1] - x[0]",
vjust = -1, parse = TRUE, color = "purple", size = 4)
We want to construct a polygon (a parallelogram, to be precise) with corners far beyond the original plot's range, so that none of it is visible within the plot. One way to achieve this is to take the existing plot's x-axis limits & shifting them outwards by the same amount as the existing plot's x-axis range: the resulting positions (in black) are pretty far out:
p3 <- p2 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
shape = 4, size = 1, stroke = 2) +
annotate(geom = "text",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
label = c("x[0] - (x[1] - x[0])", "x[1] + (x[1] - x[0])"),
vjust = -1, parse = TRUE, size = 5, hjust = c(0, 1))
p3 +
ggtitle("Calculate x-axis coordinates of two points far beyond the limits") +
annotate(geom = "segment",
x = p.x,
xend = p.x + c(-diff(p.x), diff(p.x)),
y = min(p.y), yend = min(p.y),
linetype = "dashed", size = 0.5,
arrow = arrow(ends = "both", length = unit(0.1, "inches")))
We can derive the corresponding y values associated with the x-axis positions, for each geom_abline
(in red / blue), using the standard y = a + b * x
formula:
p4 <- p3 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[2] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "red") +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[1] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "blue")
p4 +
ggtitle("Calculate the corresponding y coordinates for both ab-lines") +
annotate(geom = "text",
x = p.x[1] - diff(p.x),
y = val_intcpt + ss * (p.x[1] - diff(p.x)),
label = c("y == a[1] + b * (x[0] - (x[1] - x[0]))",
"y == a[2] + b * (x[0] - (x[1] - x[0]))"),
hjust = -0.2, parse = TRUE,
color = c("blue", "red")) +
annotate(geom = "text",
x = p.x[2] + diff(p.x),
y = val_intcpt + ss * (p.x[2] + diff(p.x)),
label = c("y == a[1] + b * (x[1] + (x[1] - x[0]))",
"y == a[2] + b * (x[1] + (x[1] - x[0]))"),
hjust = 1.2, parse = TRUE,
color = c("blue", "red"))
Now that we have the x / y coordinates for the corners, constructing the polygon is a simple matter of joining them together:
p5 <- p4 +
annotate(geom = "polygon",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
fill = "yellow", alpha = 0.4)
p5 +
ggtitle("Step 5: Draw polygon based on calculated coordinates") +
annotate(geom = "label",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
label = c("list(x[0] - (x[1] - x[0]), a[1] + b*(x[0] - (x[1] - x[0])))",
"list(x[0] - (x[1] - x[0]), a[2] + b*(x[0] - (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[2] + b*(x[1] + (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[1] + b*(x[1] + (x[1] - x[0])))"),
parse = TRUE, hjust = rep(c(0, 1), each = 2))
Apply the original plot range, & we have a polygon pretending to be a filled ribbon, with corners safely hidden out of the way beyond view:
p5 +
ggtitle("Step 6: Reset plot range to original range") +
coord_fixed(ratio = 1.5, xlim = p.x, ylim = p.y)
(Note: There's a lot of unnecessary code here, to label & colour intermediate steps for illustration purpose. For actual use, as per my original solution, none of that is necessary. But as far as explanation goes, it's either this or sketch + scan in my crappy handwriting...)
Plot a polygon, perhaps?
# let ss be the slope for geom_abline
ss <- 1
p <- ggplot() +
geom_point(data = iris, mapping = aes(x = Petal.Length, y = Sepal.Width)) +
geom_abline(intercept = 0, slope = ss, linetype = 'dashed') +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dotted')
# get plot limits
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
# create polygon coordinates, setting x positions somewhere
# beyond the current plot limits
df <- data.frame(
x = rep(c(p.x[1] - (p.x[2] - p.x[1]),
p.x[2] + (p.x[2] - p.x[1])), each = 2),
intcpt = c(val_intcpt, rev(val_intcpt))
) %>%
mutate(y = intcpt + ss * x)
# add polygon layer, & constrain to previous plot limits
p +
annotate(geom = "polygon",
x = df$x,
y = df$y,
alpha = 0.2) +
coord_cartesian(xlim = p.x, ylim = p.y)
Explanation for why it works
Let's consider a normal plot:
ss <- 0.75 # this doubles up as illustration for different slope values
p <- ggplot() +
geom_point(data = iris, aes(x = Petal.Length, y = Sepal.Width), color = "grey75") +
geom_abline(intercept = val_intcpt, slope = ss, linetype = 'dashed',
color = c("blue", "red"), size = 1) +
annotate(geom = "text", x = c(6, 3), y = c(2.3, 4), color = c("blue", "red"), size = 4,
label = c("y == a[1] + b*x", "y == a[2] + b*x"), parse = TRUE)
coord_fixed(ratio = 1.5) +
theme_classic()
p + ggtitle("Step 0: Construct plot")
Get the limits p.x
/ p.y
from the p
, & take a look at the corresponding locations in the plot itself (in purple):
p.x <- layer_scales(p)$x$get_limits()
p.y <- layer_scales(p)$y$get_limits()
p1 <- p +
geom_point(data = data.frame(x = p.x, y = p.y) %>% tidyr::complete(x, y),
aes(x = x, y = y),
size = 2, stroke = 1, color = "purple")
p1 + ggtitle("Step 1: Get plot limits")
Take note of the values for the x-axis limits (still in purple):
p2 <- p1 +
annotate(geom = "text", x = p.x, y = min(p.y), label = c("x[0]", "x[1]"),
vjust = -1, parse = TRUE, color = "purple", size = 4)
p2 +
ggtitle("Step 2: Note x-axis coordinates of limits") +
annotate(geom = "segment",
x = p.x[1] + diff(p.x),
xend = p.x[2] - diff(p.x),
y = min(p.y), yend = min(p.y),
color = "purple", linetype = "dashed", size = 1,
arrow = arrow(ends = "both")) +
annotate(geom = "text", x = mean(p.x), y = min(p.y), label = "x[1] - x[0]",
vjust = -1, parse = TRUE, color = "purple", size = 4)
We want to construct a polygon (a parallelogram, to be precise) with corners far beyond the original plot's range, so that none of it is visible within the plot. One way to achieve this is to take the existing plot's x-axis limits & shifting them outwards by the same amount as the existing plot's x-axis range: the resulting positions (in black) are pretty far out:
p3 <- p2 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
shape = 4, size = 1, stroke = 2) +
annotate(geom = "text",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)), y = min(p.y),
label = c("x[0] - (x[1] - x[0])", "x[1] + (x[1] - x[0])"),
vjust = -1, parse = TRUE, size = 5, hjust = c(0, 1))
p3 +
ggtitle("Calculate x-axis coordinates of two points far beyond the limits") +
annotate(geom = "segment",
x = p.x,
xend = p.x + c(-diff(p.x), diff(p.x)),
y = min(p.y), yend = min(p.y),
linetype = "dashed", size = 0.5,
arrow = arrow(ends = "both", length = unit(0.1, "inches")))
We can derive the corresponding y values associated with the x-axis positions, for each geom_abline
(in red / blue), using the standard y = a + b * x
formula:
p4 <- p3 +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[2] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "red") +
annotate(geom = "point",
x = c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
y = val_intcpt[1] + ss * c(p.x[1] - diff(p.x), p.x[2] + diff(p.x)),
shape = 8, size = 2, stroke = 2, col = "blue")
p4 +
ggtitle("Calculate the corresponding y coordinates for both ab-lines") +
annotate(geom = "text",
x = p.x[1] - diff(p.x),
y = val_intcpt + ss * (p.x[1] - diff(p.x)),
label = c("y == a[1] + b * (x[0] - (x[1] - x[0]))",
"y == a[2] + b * (x[0] - (x[1] - x[0]))"),
hjust = -0.2, parse = TRUE,
color = c("blue", "red")) +
annotate(geom = "text",
x = p.x[2] + diff(p.x),
y = val_intcpt + ss * (p.x[2] + diff(p.x)),
label = c("y == a[1] + b * (x[1] + (x[1] - x[0]))",
"y == a[2] + b * (x[1] + (x[1] - x[0]))"),
hjust = 1.2, parse = TRUE,
color = c("blue", "red"))
Now that we have the x / y coordinates for the corners, constructing the polygon is a simple matter of joining them together:
p5 <- p4 +
annotate(geom = "polygon",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
fill = "yellow", alpha = 0.4)
p5 +
ggtitle("Step 5: Draw polygon based on calculated coordinates") +
annotate(geom = "label",
x = rep(c(p.x[1] - diff(p.x),
p.x[2] + diff(p.x)),
each = 2),
y = c(val_intcpt + ss * (p.x[1] - diff(p.x)),
rev(val_intcpt) + ss * (p.x[2] + diff(p.x))),
label = c("list(x[0] - (x[1] - x[0]), a[1] + b*(x[0] - (x[1] - x[0])))",
"list(x[0] - (x[1] - x[0]), a[2] + b*(x[0] - (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[2] + b*(x[1] + (x[1] - x[0])))",
"list(x[1] + (x[1] - x[0]), a[1] + b*(x[1] + (x[1] - x[0])))"),
parse = TRUE, hjust = rep(c(0, 1), each = 2))
Apply the original plot range, & we have a polygon pretending to be a filled ribbon, with corners safely hidden out of the way beyond view:
p5 +
ggtitle("Step 6: Reset plot range to original range") +
coord_fixed(ratio = 1.5, xlim = p.x, ylim = p.y)
(Note: There's a lot of unnecessary code here, to label & colour intermediate steps for illustration purpose. For actual use, as per my original solution, none of that is necessary. But as far as explanation goes, it's either this or sketch + scan in my crappy handwriting...)
edited 15 hours ago
answered Oct 22 '18 at 15:33
Z.LinZ.Lin
12.3k22138
12.3k22138
yeah That is a nice hack :) I didn't knowlayer_scales
. Again, I learned a lot from you :) I will wait a tiny bit with accepting the answer though, there might be other suggestions out there
– Tjebo
Oct 22 '18 at 15:40
The solution is great for my example (and also for my requirements) but would not work for different slopes. Do you suggest editing the question to make it more general or ask a new question? Happy to do both
– Tjebo
Oct 22 '18 at 15:53
(Sorry, I feel very stupid). I admit I just do not manage to understand why your solution works at all. Why does using the coordinates of the plot limits result in the correct polygon?? That is beyond my ken
– Tjebo
Oct 22 '18 at 16:02
1
@Tjebo I just saw your questions & now I feel really bad. >_< Will update my answer to incorporate different slopes.
– Z.Lin
17 hours ago
1
@Tjebo I've updated my answer.
– Z.Lin
15 hours ago
|
show 1 more comment
yeah That is a nice hack :) I didn't knowlayer_scales
. Again, I learned a lot from you :) I will wait a tiny bit with accepting the answer though, there might be other suggestions out there
– Tjebo
Oct 22 '18 at 15:40
The solution is great for my example (and also for my requirements) but would not work for different slopes. Do you suggest editing the question to make it more general or ask a new question? Happy to do both
– Tjebo
Oct 22 '18 at 15:53
(Sorry, I feel very stupid). I admit I just do not manage to understand why your solution works at all. Why does using the coordinates of the plot limits result in the correct polygon?? That is beyond my ken
– Tjebo
Oct 22 '18 at 16:02
1
@Tjebo I just saw your questions & now I feel really bad. >_< Will update my answer to incorporate different slopes.
– Z.Lin
17 hours ago
1
@Tjebo I've updated my answer.
– Z.Lin
15 hours ago
yeah That is a nice hack :) I didn't know
layer_scales
. Again, I learned a lot from you :) I will wait a tiny bit with accepting the answer though, there might be other suggestions out there– Tjebo
Oct 22 '18 at 15:40
yeah That is a nice hack :) I didn't know
layer_scales
. Again, I learned a lot from you :) I will wait a tiny bit with accepting the answer though, there might be other suggestions out there– Tjebo
Oct 22 '18 at 15:40
The solution is great for my example (and also for my requirements) but would not work for different slopes. Do you suggest editing the question to make it more general or ask a new question? Happy to do both
– Tjebo
Oct 22 '18 at 15:53
The solution is great for my example (and also for my requirements) but would not work for different slopes. Do you suggest editing the question to make it more general or ask a new question? Happy to do both
– Tjebo
Oct 22 '18 at 15:53
(Sorry, I feel very stupid). I admit I just do not manage to understand why your solution works at all. Why does using the coordinates of the plot limits result in the correct polygon?? That is beyond my ken
– Tjebo
Oct 22 '18 at 16:02
(Sorry, I feel very stupid). I admit I just do not manage to understand why your solution works at all. Why does using the coordinates of the plot limits result in the correct polygon?? That is beyond my ken
– Tjebo
Oct 22 '18 at 16:02
1
1
@Tjebo I just saw your questions & now I feel really bad. >_< Will update my answer to incorporate different slopes.
– Z.Lin
17 hours ago
@Tjebo I just saw your questions & now I feel really bad. >_< Will update my answer to incorporate different slopes.
– Z.Lin
17 hours ago
1
1
@Tjebo I've updated my answer.
– Z.Lin
15 hours ago
@Tjebo I've updated my answer.
– Z.Lin
15 hours ago
|
show 1 more comment
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52932253%2fplot-ribbon-between-lines-created-with-geom-abline%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown