Below is a reproducible example with what the desired output would look like.
# Example
library(tidyverse)
df <- tribble(
~x,~y,
4,6,
4.5,5.5,
5,5,
5.4,4.5,
5.6,3.8,
5.7,3,
5.4,2.5,
5,2,
4.8,3)
# arbitrarily scaling because ordering needs to handle different x and y scales
df <- df %>% mutate(y = y*100)
# human eye draws the rough spiral connecting the points
ggplot(df, aes(x=x,y=y)) + geom_point()
# geom_line moves along x-axis, not desired output
ggplot(df, aes(x=x,y=y)) + geom_point() + geom_line()
# geom_path does it right - exactly what I'm after
ggplot(df, aes(x=x,y=y)) + geom_point() + geom_path()
# ...but I can't guarantee the df is going to start in the desired order:
df <- df %>% arrange(y) # arbitrarily sort by something else as orig order not guaranteed
# now geom_path doesn't work
ggplot(df, aes(x=x,y=y)) + geom_point() + geom_path()
#Q: how to go from an unordered df to a line plot with geom_path() that matches the dots in
# the same way as the human eye when just given the points.
I think I want a function that takes an original dataset, orders it like the human eye would, then can be plotted using geom_path(). I already have tried one method, that I've called the "second_min", but it doesn't work:
second_min_func <- function(df){
# try scaling (though not finished as need to scale back to orig axis after ordered)
df <- df %>% scale() %>% as_tibble()
# nest the dataframe back onto itself so can rowwise perform operations on all data
df2 <- df %>%
mutate(orig_order = row_number(),
temp=1) %>%
left_join(nest(df, data=everything()) %>% mutate(temp=1),
by="temp") %>%
select(-temp)
df3 <- df2 %>%
rowwise() %>%
mutate(
# euclidean distance for each point against all others
vec = list((x-df$x)^2 + (y-df$y)^2)
) %>%
ungroup() %>%
group_by(orig_order) %>%
mutate(
# the first minimum is 0 always as it's the point itself
second_min = which(vec[[1]]==vec[[1]][topn(vec[[1]],decreasing=FALSE)][2])
) %>%
select(x,y,orig_order,second_min)
df3 <- df3 %>% arrange(second_min)
return(df3)
}
# not desired output!
ggplot(second_min_func(df),aes(x=x,y=y)) + geom_point() + geom_path()

