Hello,
See below how I would approach this. First of all you need the dataframe in a more tidy format. Have a look at how I created df. You can build something similar for yours. Just note that if you have more than 2 values associated with a year and the same line type you will get zig zag lines so pair of points need to be unique.
In terms of the plot you will see that we figure out a distinct_count so we know how many years there are. We also use that as a filter for the dataframe so we only get portions of the data to plot . From that point we df_temp to determine if needs to be lines+markers or lines based on if it is a Cap or Val.
Finally, after adding all of them we plot the plot. I hope this works for you.
library(plotly)
library(dplyr)
df <-
data.frame(
stringsAsFactors = FALSE,
year = c(2021, 2021, 2019, 2019, 2021, 2021, 2020, 2020),
x = c(1, 2, 1, 2, 1, 2, 1, 2),
y = c(3, 6, 1, 3, 4, 7, 2, 4),
line_type = c("Cap", "Cap", "Val", "Val", "Val", "Val", "Val", "Val")
)
df
#> year x y line_type
#> 1 2021 1 3 Cap
#> 2 2021 2 6 Cap
#> 3 2019 1 1 Val
#> 4 2019 2 3 Val
#> 5 2021 1 4 Val
#> 6 2021 2 7 Val
#> 7 2020 1 2 Val
#> 8 2020 2 4 Val
distinct_count <- df %>% select(year) %>% distinct() %>% unlist()
p<-plot_ly()
for(i in 1:length(distinct_count)){
df_temp <- df %>% filter(year == distinct_count[i])
if("Cap" %in% df_temp$line_type){
df_temp_cap <- df_temp %>% filter(line_type == "Cap")
p <- add_trace(p, x = df_temp_cap$x, y= df_temp_cap$y, type = 'scatter', mode = 'lines+markers', name = paste0(df_temp_cap$year[1]))
}
if("Val" %in% df_temp$line_type){
df_temp_val <- df_temp %>% filter(line_type == "Val")
p <- add_trace(p, x = df_temp_val$x, y= df_temp_val$y, type = 'scatter', mode = 'lines', name = paste0(df_temp_val$year[1]))
}
}
p

Created on 2021-10-29 by the reprex package (v2.0.0)