Skip to content

Commit 188ee19

Browse files
committed
support "group" property to break lines
"group" property doesn't create any new trace, but if the trace mode is "lines", NA points are inserted at the "group" boundaries within the same trace. That is interpreted as the polyline break by plotlyjs.
1 parent 7ca33c9 commit 188ee19

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

R/plotly.R

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,14 +339,29 @@ plotly_build.plotly_hash <- function(l = last_plot()) {
339339
# define the dat traces
340340
points_df <- data.frame(dat_index = seq_along(dat[["x"]] %||% dat[["y"]] %||% dat[["z"]])) %>% # indices of the original data elements used in the trace FIXME properly define data length
341341
tracify_by_color(dat) %>%
342-
tracify_by_column(dat, "symbol", force_numeric=TRUE)
343-
trace_key_cols <- setdiff(colnames(points_df), "dat_index")
344-
points_df <- dplyr::arrange_(points_df, .dots = c(trace_key_cols, "dat_index")) %>%
345-
dplyr::group_by_(.dots = trace_key_cols)
342+
tracify_by_column(dat, "symbol", force_numeric=TRUE) %>%
343+
tracify_by_column(dat, "group", force_numeric=TRUE)
344+
subtrace_key_cols <- setdiff(colnames(points_df), "dat_index")
345+
trace_key_cols <- setdiff(subtrace_key_cols, "group_index")
346+
points_df <- dplyr::arrange_(points_df, .dots = c(subtrace_key_cols, "dat_index")) %>%
347+
dplyr::group_by_(.dots = subtrace_key_cols)
348+
points_df$subtrace_index <- dplyr::group_indices(points_df)
349+
points_df <- dplyr::group_by_(points_df, .dots = trace_key_cols)
346350
points_df$trace_index <- dplyr::group_indices(points_df)
347351
points_df <- dplyr::ungroup(points_df)
348352
points_df$point_order <- seq_len(nrow(points_df))
349353

354+
# polylines should be further disrupted at 'group' boundaries by inserting NAs
355+
if (grepl("lines", dat[["mode"]] %||% "markers+lines") && "group_index" %in% subtrace_key_cols) {
356+
subtrace_bound <- points_df$trace_index[-1] == points_df$trace_index[-nrow(points_df)] &
357+
points_df$subtrace_index[-1] != points_df$subtrace_index[-nrow(points_df)]
358+
if (any(subtrace_bound)) {
359+
points_df <- rbind(points_df, points_df[subtrace_bound,]) %>% dplyr::arrange(point_order)
360+
points_df$dat_index[c(FALSE, points_df$point_order[-1] == points_df$point_order[-nrow(points_df)])] <- NA
361+
points_df$point_order <- seq_len(nrow(points_df)) # order wrt added points
362+
}
363+
}
364+
350365
trace_point_indices <- attr(dplyr::group_by(points_df, trace_index), "indices")
351366
if (length(trace_point_indices) > 0) {
352367
trace_point_indices <- lapply(trace_point_indices, function(ixs) ixs+1L)

tests/testthat/test-plotly.R

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@ test_that("Using group argument doesn't transform the data in markers mode", {
2525
expect_identical(l$data[[1]]$group, iris$Species)
2626
})
2727

28+
test_that("Using group argument for scatter plot in lines mode introduces breaks (NA values separating different groups)", {
29+
p <- plot_ly(data = iris, x = Sepal.Length, y = Petal.Length, group = Species, mode = "lines")
30+
l <- expect_traces(p, 1, "scatterplot-group-lines")
31+
expect_identical(l$layout$xaxis$title, "Sepal.Length")
32+
expect_identical(l$layout$yaxis$title, "Petal.Length")
33+
n_groups <- length(unique(iris$Species))
34+
n_pts <- length(l$data[[1]]$x)
35+
expect_identical(n_pts, nrow(iris)+n_groups-1L)
36+
expect_identical(sum(is.na(l$data[[1]]$x)), n_groups-1L)
37+
expect_true(all(is.na(l$data[[1]]$group[-1]) |
38+
is.na(l$data[[1]]$group[-n_pts]) |
39+
(l$data[[1]]$group[-1] == l$data[[1]]$group[-n_pts])))
40+
})
41+
2842
test_that("Mapping a variable to symbol works", {
2943
p <- plot_ly(data = iris, x = Sepal.Length, y = Petal.Length, symbol = Species)
3044
l <- expect_traces(p, 3, "scatterplot-symbol")

0 commit comments

Comments
 (0)