Plot curved lines between two locations in ggplot2
I couldn't run cshapes
for some reason, but here's an example of how to build curves using curveGrob()
from the grid
package and ggplot2
's annotation_custom()
function. It gives you a lot of flexibility. PS: most of the params are just defaults. Edit - updated to show 2 curves.
require(grid)
g<-qplot(c(0,10),c(0,10))
myCurve<-curveGrob(0, 0, 1, 1, default.units = "npc",
curvature = 0.3, angle = 90, ncp = 20, shape = 1,
square = FALSE, squareShape = 1,
inflect = FALSE, arrow = arrow(), open = TRUE,
debug = FALSE,
name = NULL, gp = gpar(), vp = NULL)
myCurve2<-curveGrob(0, 0, 1, 1, default.units = "npc",
curvature = -0.3, angle = 60, ncp = 10, shape = 1,
square = FALSE, squareShape = 1,
inflect = FALSE, arrow = arrow(), open = TRUE,
debug = FALSE,
name = NULL, gp = gpar(), vp = NULL)
g +
annotation_custom(grob=myCurve,0,10,0,10) + # plot from 0,0 to 10,10
annotation_custom(grob=myCurve2,2.5,6,2.5,6) # plot from 2.5,2.5 to 6,6
#REFERENCE>>http://stat.ethz.ch/R-manual/R-devel/library/grid/html/grid.curve.html
How to plot a curve line between points
One way get smoothed lines instead of straight lines would be to flip x
and y
in your aesthetics, then apply geom_smooth
instead of geom_path
and then flip the coordinates through coord_flip
:
ggplot(tab, aes(x=Sample, y=N, c(0,0.16)),pch=17) +
coord_flip() +
geom_point(color='#2980B9', size = 2) +
geom_smooth(method = "loess", se = FALSE,
span = 0.25, linetype=3,color='#2980B9', size = 0.1)
connecting points with curved line on ggplot for a categorical variable on the 'x' axis
Something like this?
library(dplyr)
ggplot(oi2, aes(x = trial, y = prop, color = rs.)) +
geom_point() +
geom_line(data = . %>%
mutate(trial = as.numeric(trial)) %>%
group_by(rs.) %>%
# increase n for smoother line; can also try the other methods listed under
# ?spline, though I find "natural" looks better than some of the rest: "fmm"'s
# curves are rather drastic, & "periodic" doesn't touch all the points
summarise(x1 = list(spline(trial, prop, n = 50, method = "natural")[["x"]]),
y1 = list(spline(trial, prop, n = 50, method = "natural")[["y"]])) %>%
tidyr::unnest(),
aes(x = x1, y = y1)) +
labs(subtitle="Favorable allele over time",
y="allele frequency",
x="Groups",
title="Yield QTL markers",
col='markers')
Off topic: There are probably too many unique markers in the chart for colour to serve as an effective way to distinguish between them. You may be better off splitting this into multiple charts, with fewer markers in each. Or only give distinctive colours to the ones you wish to highlight, & leave the rest grey.
plot (ggplot ?) smooth + color area between 2 curves
Cool question since I had to give myself a crash course in using LOESS for ribbons!
First thing I'm doing is getting the data into a long shape, since that's what ggplot
will expect, and since your data has some characteristics that are kind of hidden within values. For example, if you gather
into a long shape and have, say a column key
, with a value of "inf20" and another of "sup20", those hold more information than you currently have access to, i.e. the measure type is either "inf" or "sup", and the level is 20. You can extract that information out of that column to get columns of measure types ("inf" or "sup") and levels (20, 40, 60, or 90), then map aesthetics onto those variables.
So here I'm getting the data into a long shape, then using spread
to make columns of inf
and sup
, because those will become ymin
and ymax
for the ribbons. I made level
a factor and reversed its levels, because I wanted to change the order of the ribbons being drawn such that the narrow one would come up last and be drawn on top.
library(tidyverse)
data_long <- data %>%
as_tibble() %>%
gather(key = key, value = value, -Nb_obs, -Nb_obst) %>%
mutate(measure = str_extract(key, "\\D+")) %>%
mutate(level = str_extract(key, "\\d+")) %>%
select(-key) %>%
group_by(level, measure) %>%
mutate(row = row_number()) %>%
spread(key = measure, value = value) %>%
ungroup() %>%
mutate(level = as.factor(level) %>% fct_rev())
head(data_long)
#> # A tibble: 6 x 6
#> Nb_obs Nb_obst level row inf sup
#> <dbl> <dbl> <fct> <int> <dbl> <dbl>
#> 1 0 35 20 2 2 4
#> 2 0 35 40 2 2 5
#> 3 0 35 60 2 1 6
#> 4 0 35 90 2 0 11
#> 5 0 39 20 8 3 5
#> 6 0 39 40 8 2 6
ggplot(data_long, aes(x = Nb_obst, ymin = inf, ymax = sup, fill = level)) +
geom_ribbon(alpha = 0.6) +
scale_fill_manual(values = c("20" = "darkred", "40" = "red",
"60" = "darkorange", "90" = "yellow")) +
theme_light()
But it still has the issue of being jagged, so for each level I predicted smoothed values of both inf
and sup
versus Nb_obst
using loess
. group_by
and do
yield a nested data frame, and unnest
pulls it back out into a workable form. Feel free to adjust the span
parameter, as well as other loess.control
parameters that I know very little about.
data_smooth <- data_long %>%
group_by(level) %>%
do(Nb_obst = .$Nb_obst,
inf_smooth = predict(loess(.$inf ~ .$Nb_obst, span = 0.35), .$Nb_obst),
sup_smooth = predict(loess(.$sup ~ .$Nb_obst, span = 0.35), .$Nb_obst)) %>%
unnest()
head(data_smooth)
#> # A tibble: 6 x 4
#> level Nb_obst inf_smooth sup_smooth
#> <fct> <dbl> <dbl> <dbl>
#> 1 90 35 0 11.
#> 2 90 39 0 13.4
#> 3 90 48 0.526 16.7
#> 4 90 39 0 13.4
#> 5 90 41 0 13
#> 6 90 41 0 13
ggplot(data_smooth, aes(x = Nb_obst, ymin = inf_smooth, ymax = sup_smooth, fill = level)) +
geom_ribbon(alpha = 0.6) +
scale_fill_manual(values = c("20" = "darkred", "40" = "red",
"60" = "darkorange", "90" = "yellow")) +
theme_light()
Created on 2018-05-26 by the reprex package (v0.2.0).
R ggplot multiple series curved line
As @MrFlick mentions in the comments, there are serious statistical ways of getting curved lines, which are probably off topic here.
If you just want your graph to look nicer however, you could try interpolating your data with spline
, then adding it on as another layer.
First we make some spline data, using 10 times the number of data points you had (you can increase or decrease this as desired):
library(dplyr)
dat2 <- td_results %>% select(count_id, AMV, duration_in_traffic) %>%
group_by(count_id) %>%
do(as.data.frame(spline(x= .[["AMV"]], y= .[["duration_in_traffic"]], n = nrow(.)*10)))
Then we plot, using your original data for points, but then using lines from the spline data (dat2):
library(ggplot2)
ggplot(td_results, aes(AMV, duration_in_traffic)) +
geom_point(aes(colour = factor(count_id))) +
geom_line(data = dat2, aes(x = x, y = y, colour = factor(count_id)))
This gives me the following graph from your test data:
Connecting two points with curved lines (s-ish curve) in R
Following @thelatemail's suggestion, I decided to make my edit into an answer. My solution is based on @thelatemail's answer.
I wrote a small function to draw curves, which makes use of the logistic function:
#Create the function
curveMaker <- function(x1, y1, x2, y2, ...){
curve( plogis( x, scale = 0.08, loc = (x1 + x2) /2 ) * (y2-y1) + y1,
x1, x2, add = TRUE, ...)
}
A working example is below. In this example, I want to create a plot for a taxonomy with 3 levels: parent
--> 2 children
-- > 20 grandchildren
. One child has 12 grandchildren, and the other child has 8 children.
#Prepare data:
parent <- c(1, 16)
children <- cbind(2, c(8, 28))
grandchildren <- cbind(3, (1:20)*2-1)
labels <- c("Parent ", paste("Child ", 1:2), paste(" Grandchild", 1:20) )
#Make a blank plot canvas
plot(0, type="n", ann = FALSE, xlim = c( 0.5, 3.5 ), ylim = c( 0.5, 39.5 ), axes = FALSE )
#Plot curves
#Parent and children
invisible( mapply( curveMaker,
x1 = parent[ 1 ],
y1 = parent[ 2 ],
x2 = children[ , 1 ],
y2 = children[ , 2 ],
col = gray( 0.6, alpha = 0.6 ), lwd = 1.5 ) )
#Children and grandchildren
invisible( mapply( curveMaker,
x1 = children[ 1, 1 ],
y1 = children[ 1, 2 ],
x2 = grandchildren[ 1:8 , 1 ],
y2 = grandchildren[ 1:8, 2 ],
col = gray( 0.6, alpha = 0.6 ), lwd = 1.5 ) )
invisible( mapply( curveMaker,
x1 = children[ 2, 1 ],
y1 = children[ 2, 2 ],
x2 = grandchildren[ 9:20 , 1 ],
y2 = grandchildren[ 9:20, 2 ],
col = gray( 0.6, alpha = 0.6 ), lwd = 1.5 ) )
#Plot text
text( x = c(parent[1], children[,1], grandchildren[,1]),
y = c(parent[2], children[,2], grandchildren[,2]),
labels = labels,
pos = rep(c(2, 4), c(3, 20) ) )
#Plot points
points( x = c(parent[1], children[,1], grandchildren[,1]),
y = c(parent[2], children[,2], grandchildren[,2]),
pch = 21, bg = "white", col="#3182bd", lwd=2.5, cex=1)
Draw curved lines in ggmap, geom_curve not working
I think using coord_cartesian()
give you what you want. Using the 5 rows showed in your post
map <- get_map(location = "Amsterdam", zoom = 11)
ggmap(map) +
geom_point(data = df_vertices,
aes(x = Longitude, y = Latitude, size = scaledkWh),
colour = "red", alpha =0.5) +
geom_curve(data = df,
aes(x = Longitude_from, y = Latitude_from, xend = Longitude_to, yend = Latitude_to),
arrow = arrow(angle = 15, ends = "first", length = unit(0.5, "cm"), type = "closed"),
size = df$scaledAmount, alpha = 0.5, curvature = 0.15, inherit.aes = TRUE)
scale_size_continuous(range=c(1,30)) +
coord_cartesian()
Related Topics
Rscript Detect If R Script Is Being Called/Sourced from Another Script
Select Rows in a Dataframe in R Based on Values in One Row
Subset a Data Frame Based on Value Pairs Stored in Independent Ordered Vectors
R Data.Table Join: SQL "Select *" Alike Syntax in Joined Tables
Syntax Highlighting for Python Chunks Does Not Work
How to Get a List of All Possible Partitions of a Vector in R
Replace Every Single Character at the Start of String That Matches a Regex Pattern
Setting Working Directory: Julia Versus R
Extracting Output from Principal Function in Psych Package as a Data Frame
How to Scrape a Table with Rvest and Xpath
How to Calculate the Median on Grouped Dataset
Nls Troubles: Missing Value or an Infinity Produced When Evaluating the Model
How to Load Xlsx File Using Fread Function
How to Change Factor Labels into String in a Data Frame
How to Read the Files in a Directory in Sorted Order Using R
Modify Lm or Loess Function to Use It Within Ggplot2's Geom_Smooth