我有一个大型数据集,其中包含随时间变化的观察值。我正在使用
plotly
来可视化趋势。
目前,因为我有特定的自定义颜色、宽度和线条类型,所以我一直将每个主题视为单独的跟踪,并在每次出现新值时手动重新排列它们 - 希望图例顺序与最新值匹配。
我接近一个更优雅的解决方案,但不确定如何应用
width
参数以及如何对图例进行排序,以便具有最高最新值的主题位于第一个(即 Susan 具有最低的 2000 值,因此将是最后)。
library(tidyverse)
library(plotly)
# raw data
df <-
tribble(
~Year, ~Subject, ~Value,
1980, 'A', 100,
1990, 'A', 200,
2000, 'A', 250,
1980, 'B', 400,
1990, 'B', 300,
2000, 'B', 100,
1980, 'C', 200,
1990, 'C', 100,
2000, 'C', 500
)
# each subject has specific custom viz elements
custom_stuff <-
tribble(
~Subject, ~Name, ~LineColor, ~LineType, ~LineWidth,
'A', 'John', 'blue', 'solid', 2,
'B', 'Susan', '#ef0107', 'dash', 1,
'C', 'Subject C', 'orange', 'dot', 1
)
# i'm currently transposing the data like this
df_wide <-
df |>
pivot_wider(names_from = 'Subject', values_from = 'Value')
# and then manually applying my custom elements and manually ordering the traces based on most recent value. yuck.
plot_ly(df_wide, x = ~Year) |>
add_trace(y = ~C, name = 'Subject C', type = 'scatter', mode = 'lines',
line = list(shape = 'spline', color = 'orange', width = 1, dash = 'dot')) |>
add_trace(y = ~A, name = 'John', type = 'scatter', mode = 'lines',
line = list(shape = 'spline', color = 'blue', width = 2, dash = 'solid')) |>
add_trace(y = ~B, name = 'Susan', type = 'scatter', mode = 'lines',
line = list(shape = 'spline', color = '#ef0107', width = 1, dash = 'dash'))
# i'd like to do something more dynamic and elegant like this, but unsure how to handle width and ordering of legend.
custom_df <-
df |>
inner_join(custom_stuff, by = 'Subject')
plot_ly(custom_df,
x = ~Year,
y = ~Value,
color = ~I(LineColor),
name = ~Name,
type = 'scatter',
mode = 'lines',
linetype = ~I(LineType),
# width = ~I(LineWidth),
line = list(shape = 'spline', smoothing = 1.3))
这是一种可能的方法,它建立在使用广泛数据集的第一种方法的基础上,但使用
Reduce
动态添加跟踪,并使用一些数据整理来确定主题/跟踪的顺序:
library(tidyverse)
library(plotly)
# Order of subjects and traces
subject_order <- df |>
slice_max(Year, by = Subject) |>
arrange(desc(Year), desc(Value)) |>
mutate(Subject = fct_inorder(Subject)) |>
pull(Subject) |>
levels()
plot_ly(df_wide, x = ~Year) |>
Reduce(\(x, y) {
custom_stuff <- custom_stuff |> filter(Subject == y)
add_trace(
x,
y = reformulate(y), name = custom_stuff$Name, type = "scatter", mode = "lines",
line = list(
shape = "spline", color = custom_stuff$LineColor,
width = custom_stuff$LineWidth,
dash = custom_stuff$LineType
)
)
}, x = subject_order, init = _)