Optimising Shiny Dashboard plot redraw
I have built a shiny dashboard which has a set of data loaded in as a data frame. It uses dplyr to then select columns, mutate new columns if needed, apply a set of filters and then plot using a variety of high-level ggplot2-based packages.
We try to do the data load, select and mutate just the once. The filtering is sat in a reactive variable, accessed by the plot, and is based upon different input values.
As far as I see this is a pretty standard and typical use case.
I'm wondering whether anyone could advise on workflow patterns to make the output more responsive.
There are two scenarios I encounter with this writing pattern which appear to cause significant user interface delay which I'd like to avoid:
Firstly, when the dashboard first loads it tries to plot the charts using NULL data. I've found I can get around this by using if(is.null(my_data_frame)) and returning geom_blank() rather than our plot. Is there a neater / faster way to do this?
Secondly (and more challengingly): to the right of my plot are a (potentially large) set of filter options to allow the user to analyse subsets. If the user clicks several of these options in rapid succession, Shiny will repeatedly recalculate our reactive() value and replot the chart for each click event: where the user actually just needed to set or clear 5 options. Is there a way to prevent this happening - so if the recalculation isn't complete we don't continue with the plot in progress as we've just made the data stale? Or do you think about grouping options with an update button to prevent this?
r shiny
add a comment |
I have built a shiny dashboard which has a set of data loaded in as a data frame. It uses dplyr to then select columns, mutate new columns if needed, apply a set of filters and then plot using a variety of high-level ggplot2-based packages.
We try to do the data load, select and mutate just the once. The filtering is sat in a reactive variable, accessed by the plot, and is based upon different input values.
As far as I see this is a pretty standard and typical use case.
I'm wondering whether anyone could advise on workflow patterns to make the output more responsive.
There are two scenarios I encounter with this writing pattern which appear to cause significant user interface delay which I'd like to avoid:
Firstly, when the dashboard first loads it tries to plot the charts using NULL data. I've found I can get around this by using if(is.null(my_data_frame)) and returning geom_blank() rather than our plot. Is there a neater / faster way to do this?
Secondly (and more challengingly): to the right of my plot are a (potentially large) set of filter options to allow the user to analyse subsets. If the user clicks several of these options in rapid succession, Shiny will repeatedly recalculate our reactive() value and replot the chart for each click event: where the user actually just needed to set or clear 5 options. Is there a way to prevent this happening - so if the recalculation isn't complete we don't continue with the plot in progress as we've just made the data stale? Or do you think about grouping options with an update button to prevent this?
r shiny
You can put your calculations ineventReactive()
instead of justreactive()
. Have the calculation run when user presses someactionButton
after checking/unchecking options. For more help provide minimum working example.
– Shree
Nov 15 '18 at 2:30
add a comment |
I have built a shiny dashboard which has a set of data loaded in as a data frame. It uses dplyr to then select columns, mutate new columns if needed, apply a set of filters and then plot using a variety of high-level ggplot2-based packages.
We try to do the data load, select and mutate just the once. The filtering is sat in a reactive variable, accessed by the plot, and is based upon different input values.
As far as I see this is a pretty standard and typical use case.
I'm wondering whether anyone could advise on workflow patterns to make the output more responsive.
There are two scenarios I encounter with this writing pattern which appear to cause significant user interface delay which I'd like to avoid:
Firstly, when the dashboard first loads it tries to plot the charts using NULL data. I've found I can get around this by using if(is.null(my_data_frame)) and returning geom_blank() rather than our plot. Is there a neater / faster way to do this?
Secondly (and more challengingly): to the right of my plot are a (potentially large) set of filter options to allow the user to analyse subsets. If the user clicks several of these options in rapid succession, Shiny will repeatedly recalculate our reactive() value and replot the chart for each click event: where the user actually just needed to set or clear 5 options. Is there a way to prevent this happening - so if the recalculation isn't complete we don't continue with the plot in progress as we've just made the data stale? Or do you think about grouping options with an update button to prevent this?
r shiny
I have built a shiny dashboard which has a set of data loaded in as a data frame. It uses dplyr to then select columns, mutate new columns if needed, apply a set of filters and then plot using a variety of high-level ggplot2-based packages.
We try to do the data load, select and mutate just the once. The filtering is sat in a reactive variable, accessed by the plot, and is based upon different input values.
As far as I see this is a pretty standard and typical use case.
I'm wondering whether anyone could advise on workflow patterns to make the output more responsive.
There are two scenarios I encounter with this writing pattern which appear to cause significant user interface delay which I'd like to avoid:
Firstly, when the dashboard first loads it tries to plot the charts using NULL data. I've found I can get around this by using if(is.null(my_data_frame)) and returning geom_blank() rather than our plot. Is there a neater / faster way to do this?
Secondly (and more challengingly): to the right of my plot are a (potentially large) set of filter options to allow the user to analyse subsets. If the user clicks several of these options in rapid succession, Shiny will repeatedly recalculate our reactive() value and replot the chart for each click event: where the user actually just needed to set or clear 5 options. Is there a way to prevent this happening - so if the recalculation isn't complete we don't continue with the plot in progress as we've just made the data stale? Or do you think about grouping options with an update button to prevent this?
r shiny
r shiny
asked Nov 15 '18 at 2:08
Andrew HillAndrew Hill
8219
8219
You can put your calculations ineventReactive()
instead of justreactive()
. Have the calculation run when user presses someactionButton
after checking/unchecking options. For more help provide minimum working example.
– Shree
Nov 15 '18 at 2:30
add a comment |
You can put your calculations ineventReactive()
instead of justreactive()
. Have the calculation run when user presses someactionButton
after checking/unchecking options. For more help provide minimum working example.
– Shree
Nov 15 '18 at 2:30
You can put your calculations in
eventReactive()
instead of just reactive()
. Have the calculation run when user presses some actionButton
after checking/unchecking options. For more help provide minimum working example.– Shree
Nov 15 '18 at 2:30
You can put your calculations in
eventReactive()
instead of just reactive()
. Have the calculation run when user presses some actionButton
after checking/unchecking options. For more help provide minimum working example.– Shree
Nov 15 '18 at 2:30
add a comment |
2 Answers
2
active
oldest
votes
In response to your second bullet. Check out shiny's debounce/throttle capabilities. These should slow down the reactive response so your user can finish with the UI control before the chart or presentation element recalculates.
That's definitely worth trying: I may try using an update button to specifically wait until the user has finished messing with the configuration before making the changes first. Thanks!
– Andrew Hill
Nov 15 '18 at 16:32
add a comment |
For your first question, try using the req
function inside your reactive block. If your plot is waiting on the data frame to load, you can put the code for loading the data frame in a named reactive block (it seems like you may have already done this), then pass that to req
. This will prevent the plot from attempting to render until it receives a valid value for whatever you passed to req
.
For the second, I'd recommend wrapping your plot render in an observeEvent
and having an 'Update' button, if you typically expect users to change multiple options between desired plot updates.
Finally, for added performance, I just saw today that Shiny v1.2.0 has either just been released or is about to be, the major feature of which is plot caching. You can find more details HERE.
These are great suggestions - thank you! Hadn't seen req before. I had also just picked up the plot cacheing only today having had a read around.
– Andrew Hill
Nov 15 '18 at 16:31
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53311423%2foptimising-shiny-dashboard-plot-redraw%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
In response to your second bullet. Check out shiny's debounce/throttle capabilities. These should slow down the reactive response so your user can finish with the UI control before the chart or presentation element recalculates.
That's definitely worth trying: I may try using an update button to specifically wait until the user has finished messing with the configuration before making the changes first. Thanks!
– Andrew Hill
Nov 15 '18 at 16:32
add a comment |
In response to your second bullet. Check out shiny's debounce/throttle capabilities. These should slow down the reactive response so your user can finish with the UI control before the chart or presentation element recalculates.
That's definitely worth trying: I may try using an update button to specifically wait until the user has finished messing with the configuration before making the changes first. Thanks!
– Andrew Hill
Nov 15 '18 at 16:32
add a comment |
In response to your second bullet. Check out shiny's debounce/throttle capabilities. These should slow down the reactive response so your user can finish with the UI control before the chart or presentation element recalculates.
In response to your second bullet. Check out shiny's debounce/throttle capabilities. These should slow down the reactive response so your user can finish with the UI control before the chart or presentation element recalculates.
answered Nov 15 '18 at 3:50
KgreyKgrey
1613
1613
That's definitely worth trying: I may try using an update button to specifically wait until the user has finished messing with the configuration before making the changes first. Thanks!
– Andrew Hill
Nov 15 '18 at 16:32
add a comment |
That's definitely worth trying: I may try using an update button to specifically wait until the user has finished messing with the configuration before making the changes first. Thanks!
– Andrew Hill
Nov 15 '18 at 16:32
That's definitely worth trying: I may try using an update button to specifically wait until the user has finished messing with the configuration before making the changes first. Thanks!
– Andrew Hill
Nov 15 '18 at 16:32
That's definitely worth trying: I may try using an update button to specifically wait until the user has finished messing with the configuration before making the changes first. Thanks!
– Andrew Hill
Nov 15 '18 at 16:32
add a comment |
For your first question, try using the req
function inside your reactive block. If your plot is waiting on the data frame to load, you can put the code for loading the data frame in a named reactive block (it seems like you may have already done this), then pass that to req
. This will prevent the plot from attempting to render until it receives a valid value for whatever you passed to req
.
For the second, I'd recommend wrapping your plot render in an observeEvent
and having an 'Update' button, if you typically expect users to change multiple options between desired plot updates.
Finally, for added performance, I just saw today that Shiny v1.2.0 has either just been released or is about to be, the major feature of which is plot caching. You can find more details HERE.
These are great suggestions - thank you! Hadn't seen req before. I had also just picked up the plot cacheing only today having had a read around.
– Andrew Hill
Nov 15 '18 at 16:31
add a comment |
For your first question, try using the req
function inside your reactive block. If your plot is waiting on the data frame to load, you can put the code for loading the data frame in a named reactive block (it seems like you may have already done this), then pass that to req
. This will prevent the plot from attempting to render until it receives a valid value for whatever you passed to req
.
For the second, I'd recommend wrapping your plot render in an observeEvent
and having an 'Update' button, if you typically expect users to change multiple options between desired plot updates.
Finally, for added performance, I just saw today that Shiny v1.2.0 has either just been released or is about to be, the major feature of which is plot caching. You can find more details HERE.
These are great suggestions - thank you! Hadn't seen req before. I had also just picked up the plot cacheing only today having had a read around.
– Andrew Hill
Nov 15 '18 at 16:31
add a comment |
For your first question, try using the req
function inside your reactive block. If your plot is waiting on the data frame to load, you can put the code for loading the data frame in a named reactive block (it seems like you may have already done this), then pass that to req
. This will prevent the plot from attempting to render until it receives a valid value for whatever you passed to req
.
For the second, I'd recommend wrapping your plot render in an observeEvent
and having an 'Update' button, if you typically expect users to change multiple options between desired plot updates.
Finally, for added performance, I just saw today that Shiny v1.2.0 has either just been released or is about to be, the major feature of which is plot caching. You can find more details HERE.
For your first question, try using the req
function inside your reactive block. If your plot is waiting on the data frame to load, you can put the code for loading the data frame in a named reactive block (it seems like you may have already done this), then pass that to req
. This will prevent the plot from attempting to render until it receives a valid value for whatever you passed to req
.
For the second, I'd recommend wrapping your plot render in an observeEvent
and having an 'Update' button, if you typically expect users to change multiple options between desired plot updates.
Finally, for added performance, I just saw today that Shiny v1.2.0 has either just been released or is about to be, the major feature of which is plot caching. You can find more details HERE.
answered Nov 15 '18 at 5:27
Eric BurdenEric Burden
512
512
These are great suggestions - thank you! Hadn't seen req before. I had also just picked up the plot cacheing only today having had a read around.
– Andrew Hill
Nov 15 '18 at 16:31
add a comment |
These are great suggestions - thank you! Hadn't seen req before. I had also just picked up the plot cacheing only today having had a read around.
– Andrew Hill
Nov 15 '18 at 16:31
These are great suggestions - thank you! Hadn't seen req before. I had also just picked up the plot cacheing only today having had a read around.
– Andrew Hill
Nov 15 '18 at 16:31
These are great suggestions - thank you! Hadn't seen req before. I had also just picked up the plot cacheing only today having had a read around.
– Andrew Hill
Nov 15 '18 at 16:31
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53311423%2foptimising-shiny-dashboard-plot-redraw%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
You can put your calculations in
eventReactive()
instead of justreactive()
. Have the calculation run when user presses someactionButton
after checking/unchecking options. For more help provide minimum working example.– Shree
Nov 15 '18 at 2:30