From 7177618c259e573efcbb300c8b48cd86336ed4cf Mon Sep 17 00:00:00 2001 From: AliciaSchep Date: Tue, 4 Sep 2018 20:51:51 -0700 Subject: [PATCH 1/5] add informative errors when xvar or yvar not in data for nearPoints and brushedPoints --- R/image-interact.R | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/R/image-interact.R b/R/image-interact.R index cad6291ea..b2b1cf1fa 100644 --- a/R/image-interact.R +++ b/R/image-interact.R @@ -86,6 +86,8 @@ brushedPoints <- function(df, brush, xvar = NULL, yvar = NULL, if (use_x) { if (is.null(xvar)) stop("brushedPoints: not able to automatically infer `xvar` from brush") + if (!(xvar %in% names(df))) + stop("brushedPoints: `xvar` not in names of input") # Extract data values from the data frame x <- asNumber(df[[xvar]]) keep_rows <- keep_rows & (x >= brush$xmin & x <= brush$xmax) @@ -93,6 +95,8 @@ brushedPoints <- function(df, brush, xvar = NULL, yvar = NULL, if (use_y) { if (is.null(yvar)) stop("brushedPoints: not able to automatically infer `yvar` from brush") + if (!(yvar %in% names(df))) + stop("brushedPoints: `yvar` not in names of input") y <- asNumber(df[[yvar]]) keep_rows <- keep_rows & (y >= brush$ymin & y <= brush$ymax) } @@ -245,6 +249,11 @@ nearPoints <- function(df, coordinfo, xvar = NULL, yvar = NULL, if (is.null(yvar)) stop("nearPoints: not able to automatically infer `yvar` from coordinfo") + if (!(xvar %in% names(df))) + stop("nearPoints: `xvar` not in names of input") + if (!(yvar %in% names(df))) + stop("nearPoints: `yvar` not in names of input") + # Extract data values from the data frame x <- asNumber(df[[xvar]]) y <- asNumber(df[[yvar]]) From 72dda258350f80eec27f16afee8db43f89471b11 Mon Sep 17 00:00:00 2001 From: AliciaSchep Date: Sun, 16 Sep 2018 22:45:53 -0700 Subject: [PATCH 2/5] evaluate xvar and yvar for nearPoints and brushedPoints --- R/image-interact.R | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/R/image-interact.R b/R/image-interact.R index b2b1cf1fa..d50cdb12b 100644 --- a/R/image-interact.R +++ b/R/image-interact.R @@ -1,3 +1,9 @@ +# Helper function for getting potentially transformed variable from input +# data.frame to nearPoints or brushPoints +eval_var_in_data <- function(var, data, envir) { + eval(parse(text = var), data, envir) +} + #' Find rows of data that are selected by a brush #' #' This function returns rows from a data frame which are under a brush used @@ -86,18 +92,15 @@ brushedPoints <- function(df, brush, xvar = NULL, yvar = NULL, if (use_x) { if (is.null(xvar)) stop("brushedPoints: not able to automatically infer `xvar` from brush") - if (!(xvar %in% names(df))) - stop("brushedPoints: `xvar` not in names of input") # Extract data values from the data frame - x <- asNumber(df[[xvar]]) + x <- asNumber(eval_var_in_data(xvar, df, envir = parent.frame())) keep_rows <- keep_rows & (x >= brush$xmin & x <= brush$xmax) } if (use_y) { if (is.null(yvar)) stop("brushedPoints: not able to automatically infer `yvar` from brush") - if (!(yvar %in% names(df))) - stop("brushedPoints: `yvar` not in names of input") - y <- asNumber(df[[yvar]]) + # Extract data values from the data frame + y <- asNumber(eval_var_in_data(yvar, df, envir = parent.frame())) keep_rows <- keep_rows & (y >= brush$ymin & y <= brush$ymax) } @@ -249,14 +252,9 @@ nearPoints <- function(df, coordinfo, xvar = NULL, yvar = NULL, if (is.null(yvar)) stop("nearPoints: not able to automatically infer `yvar` from coordinfo") - if (!(xvar %in% names(df))) - stop("nearPoints: `xvar` not in names of input") - if (!(yvar %in% names(df))) - stop("nearPoints: `yvar` not in names of input") - # Extract data values from the data frame - x <- asNumber(df[[xvar]]) - y <- asNumber(df[[yvar]]) + x <- asNumber(eval_var_in_data(xvar, df, envir = parent.frame())) + y <- asNumber(eval_var_in_data(yvar, df, envir = parent.frame())) # Get the coordinates of the point (in img pixel coordinates) point_img <- scaleCoords(coordinfo$x, coordinfo$y, coordinfo) From 67ae2a39ba34f5a0073d377e3bff915d936a9dfa Mon Sep 17 00:00:00 2001 From: AliciaSchep Date: Sun, 16 Sep 2018 23:07:08 -0700 Subject: [PATCH 3/5] update documentation to reflect new options for xvar and yvar --- R/image-interact.R | 14 +++++--------- man/brushedPoints.Rd | 14 +++++--------- man/nearPoints.Rd | 14 ++++++++------ 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/R/image-interact.R b/R/image-interact.R index d50cdb12b..3bd27f29d 100644 --- a/R/image-interact.R +++ b/R/image-interact.R @@ -26,12 +26,7 @@ eval_var_in_data <- function(var, data, envir) { #' column names; that information will already be contained in the brush, #' provided that variables are in the original data, and not computed. For #' example, with \code{ggplot(cars, aes(x=speed, y=dist)) + geom_point()}, you -#' could use \code{brushedPoints(cars, input$cars_brush)}. If, however, you use -#' a computed column, like \code{ggplot(cars, aes(x=speed/2, y=dist)) + -#' geom_point()}, then it will not be able to automatically extract column names -#' and filter on them. If you want to use this function to filter data, it is -#' recommended that you not use computed columns; instead, modify the data -#' first, and then make the plot with "raw" columns in the modified data. +#' could use \code{brushedPoints(cars, input$cars_brush)}. #' #' If a specified x or y column is a factor, then it will be coerced to an #' integer vector. If it is a character vector, then it will be coerced to a @@ -45,9 +40,10 @@ eval_var_in_data <- function(var, data, envir) { #' @param brush The data from a brush, such as \code{input$plot_brush}. #' @param df A data frame from which to select rows. #' @param xvar,yvar A string with the name of the variable on the x or y axis. -#' This must also be the name of a column in \code{df}. If absent, then this -#' function will try to infer the variable from the brush (only works for -#' ggplot2). +#' This should be the name of a column in \code{df} or a string with an +#' expression that will be evaluated in the context of \code{df}. If absent, +#' then this function will try to infer the variable from the brush (only works +#' for ggplot2). #' @param panelvar1,panelvar2 Each of these is a string with the name of a panel #' variable. For example, if with ggplot2, you facet on a variable called #' \code{cyl}, then you can use \code{"cyl"} here. However, specifying the diff --git a/man/brushedPoints.Rd b/man/brushedPoints.Rd index 1760b47f9..19e7cb28d 100644 --- a/man/brushedPoints.Rd +++ b/man/brushedPoints.Rd @@ -13,9 +13,10 @@ brushedPoints(df, brush, xvar = NULL, yvar = NULL, panelvar1 = NULL, \item{brush}{The data from a brush, such as \code{input$plot_brush}.} \item{xvar, yvar}{A string with the name of the variable on the x or y axis. -This must also be the name of a column in \code{df}. If absent, then this -function will try to infer the variable from the brush (only works for -ggplot2).} +This should be the name of a column in \code{df} or a string with an +expression that will be evaluated in the context of \code{df}. If absent, +then this function will try to infer the variable from the brush (only works +for ggplot2).} \item{panelvar1, panelvar2}{Each of these is a string with the name of a panel variable. For example, if with ggplot2, you facet on a variable called @@ -50,12 +51,7 @@ For plots created with ggplot2, it should not be necessary to specify the column names; that information will already be contained in the brush, provided that variables are in the original data, and not computed. For example, with \code{ggplot(cars, aes(x=speed, y=dist)) + geom_point()}, you -could use \code{brushedPoints(cars, input$cars_brush)}. If, however, you use -a computed column, like \code{ggplot(cars, aes(x=speed/2, y=dist)) + -geom_point()}, then it will not be able to automatically extract column names -and filter on them. If you want to use this function to filter data, it is -recommended that you not use computed columns; instead, modify the data -first, and then make the plot with "raw" columns in the modified data. +could use \code{brushedPoints(cars, input$cars_brush)}. If a specified x or y column is a factor, then it will be coerced to an integer vector. If it is a character vector, then it will be coerced to a diff --git a/man/nearPoints.Rd b/man/nearPoints.Rd index 4daeb92c4..39ae5442a 100644 --- a/man/nearPoints.Rd +++ b/man/nearPoints.Rd @@ -14,14 +14,16 @@ nearPoints(df, coordinfo, xvar = NULL, yvar = NULL, panelvar1 = NULL, \item{coordinfo}{The data from a mouse event, such as \code{input$plot_click}.} \item{xvar}{A string with the name of the variable on the x or y axis. -This must also be the name of a column in \code{df}. If absent, then this -function will try to infer the variable from the brush (only works for -ggplot2).} +This should be the name of a column in \code{df} or a string with an +expression that will be evaluated in the context of \code{df}. If absent, +then this function will try to infer the variable from the brush (only works +for ggplot2).} \item{yvar}{A string with the name of the variable on the x or y axis. -This must also be the name of a column in \code{df}. If absent, then this -function will try to infer the variable from the brush (only works for -ggplot2).} +This should be the name of a column in \code{df} or a string with an +expression that will be evaluated in the context of \code{df}. If absent, +then this function will try to infer the variable from the brush (only works +for ggplot2).} \item{panelvar1}{Each of these is a string with the name of a panel variable. For example, if with ggplot2, you facet on a variable called From 00f08b8ec65fa2162e1ed43011d7bc854b8f88c0 Mon Sep 17 00:00:00 2001 From: AliciaSchep Date: Mon, 17 Sep 2018 09:41:04 -0700 Subject: [PATCH 4/5] revert two previous commits --- R/image-interact.R | 38 ++++++++++++++++++++++---------------- man/brushedPoints.Rd | 14 +++++++++----- man/nearPoints.Rd | 14 ++++++-------- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/R/image-interact.R b/R/image-interact.R index 3bd27f29d..b2b1cf1fa 100644 --- a/R/image-interact.R +++ b/R/image-interact.R @@ -1,9 +1,3 @@ -# Helper function for getting potentially transformed variable from input -# data.frame to nearPoints or brushPoints -eval_var_in_data <- function(var, data, envir) { - eval(parse(text = var), data, envir) -} - #' Find rows of data that are selected by a brush #' #' This function returns rows from a data frame which are under a brush used @@ -26,7 +20,12 @@ eval_var_in_data <- function(var, data, envir) { #' column names; that information will already be contained in the brush, #' provided that variables are in the original data, and not computed. For #' example, with \code{ggplot(cars, aes(x=speed, y=dist)) + geom_point()}, you -#' could use \code{brushedPoints(cars, input$cars_brush)}. +#' could use \code{brushedPoints(cars, input$cars_brush)}. If, however, you use +#' a computed column, like \code{ggplot(cars, aes(x=speed/2, y=dist)) + +#' geom_point()}, then it will not be able to automatically extract column names +#' and filter on them. If you want to use this function to filter data, it is +#' recommended that you not use computed columns; instead, modify the data +#' first, and then make the plot with "raw" columns in the modified data. #' #' If a specified x or y column is a factor, then it will be coerced to an #' integer vector. If it is a character vector, then it will be coerced to a @@ -40,10 +39,9 @@ eval_var_in_data <- function(var, data, envir) { #' @param brush The data from a brush, such as \code{input$plot_brush}. #' @param df A data frame from which to select rows. #' @param xvar,yvar A string with the name of the variable on the x or y axis. -#' This should be the name of a column in \code{df} or a string with an -#' expression that will be evaluated in the context of \code{df}. If absent, -#' then this function will try to infer the variable from the brush (only works -#' for ggplot2). +#' This must also be the name of a column in \code{df}. If absent, then this +#' function will try to infer the variable from the brush (only works for +#' ggplot2). #' @param panelvar1,panelvar2 Each of these is a string with the name of a panel #' variable. For example, if with ggplot2, you facet on a variable called #' \code{cyl}, then you can use \code{"cyl"} here. However, specifying the @@ -88,15 +86,18 @@ brushedPoints <- function(df, brush, xvar = NULL, yvar = NULL, if (use_x) { if (is.null(xvar)) stop("brushedPoints: not able to automatically infer `xvar` from brush") + if (!(xvar %in% names(df))) + stop("brushedPoints: `xvar` not in names of input") # Extract data values from the data frame - x <- asNumber(eval_var_in_data(xvar, df, envir = parent.frame())) + x <- asNumber(df[[xvar]]) keep_rows <- keep_rows & (x >= brush$xmin & x <= brush$xmax) } if (use_y) { if (is.null(yvar)) stop("brushedPoints: not able to automatically infer `yvar` from brush") - # Extract data values from the data frame - y <- asNumber(eval_var_in_data(yvar, df, envir = parent.frame())) + if (!(yvar %in% names(df))) + stop("brushedPoints: `yvar` not in names of input") + y <- asNumber(df[[yvar]]) keep_rows <- keep_rows & (y >= brush$ymin & y <= brush$ymax) } @@ -248,9 +249,14 @@ nearPoints <- function(df, coordinfo, xvar = NULL, yvar = NULL, if (is.null(yvar)) stop("nearPoints: not able to automatically infer `yvar` from coordinfo") + if (!(xvar %in% names(df))) + stop("nearPoints: `xvar` not in names of input") + if (!(yvar %in% names(df))) + stop("nearPoints: `yvar` not in names of input") + # Extract data values from the data frame - x <- asNumber(eval_var_in_data(xvar, df, envir = parent.frame())) - y <- asNumber(eval_var_in_data(yvar, df, envir = parent.frame())) + x <- asNumber(df[[xvar]]) + y <- asNumber(df[[yvar]]) # Get the coordinates of the point (in img pixel coordinates) point_img <- scaleCoords(coordinfo$x, coordinfo$y, coordinfo) diff --git a/man/brushedPoints.Rd b/man/brushedPoints.Rd index 19e7cb28d..1760b47f9 100644 --- a/man/brushedPoints.Rd +++ b/man/brushedPoints.Rd @@ -13,10 +13,9 @@ brushedPoints(df, brush, xvar = NULL, yvar = NULL, panelvar1 = NULL, \item{brush}{The data from a brush, such as \code{input$plot_brush}.} \item{xvar, yvar}{A string with the name of the variable on the x or y axis. -This should be the name of a column in \code{df} or a string with an -expression that will be evaluated in the context of \code{df}. If absent, -then this function will try to infer the variable from the brush (only works -for ggplot2).} +This must also be the name of a column in \code{df}. If absent, then this +function will try to infer the variable from the brush (only works for +ggplot2).} \item{panelvar1, panelvar2}{Each of these is a string with the name of a panel variable. For example, if with ggplot2, you facet on a variable called @@ -51,7 +50,12 @@ For plots created with ggplot2, it should not be necessary to specify the column names; that information will already be contained in the brush, provided that variables are in the original data, and not computed. For example, with \code{ggplot(cars, aes(x=speed, y=dist)) + geom_point()}, you -could use \code{brushedPoints(cars, input$cars_brush)}. +could use \code{brushedPoints(cars, input$cars_brush)}. If, however, you use +a computed column, like \code{ggplot(cars, aes(x=speed/2, y=dist)) + +geom_point()}, then it will not be able to automatically extract column names +and filter on them. If you want to use this function to filter data, it is +recommended that you not use computed columns; instead, modify the data +first, and then make the plot with "raw" columns in the modified data. If a specified x or y column is a factor, then it will be coerced to an integer vector. If it is a character vector, then it will be coerced to a diff --git a/man/nearPoints.Rd b/man/nearPoints.Rd index 39ae5442a..4daeb92c4 100644 --- a/man/nearPoints.Rd +++ b/man/nearPoints.Rd @@ -14,16 +14,14 @@ nearPoints(df, coordinfo, xvar = NULL, yvar = NULL, panelvar1 = NULL, \item{coordinfo}{The data from a mouse event, such as \code{input$plot_click}.} \item{xvar}{A string with the name of the variable on the x or y axis. -This should be the name of a column in \code{df} or a string with an -expression that will be evaluated in the context of \code{df}. If absent, -then this function will try to infer the variable from the brush (only works -for ggplot2).} +This must also be the name of a column in \code{df}. If absent, then this +function will try to infer the variable from the brush (only works for +ggplot2).} \item{yvar}{A string with the name of the variable on the x or y axis. -This should be the name of a column in \code{df} or a string with an -expression that will be evaluated in the context of \code{df}. If absent, -then this function will try to infer the variable from the brush (only works -for ggplot2).} +This must also be the name of a column in \code{df}. If absent, then this +function will try to infer the variable from the brush (only works for +ggplot2).} \item{panelvar1}{Each of these is a string with the name of a panel variable. For example, if with ggplot2, you facet on a variable called From eeb264da8e81133856c115adaeffeb396f7dd243 Mon Sep 17 00:00:00 2001 From: AliciaSchep Date: Mon, 17 Sep 2018 09:45:40 -0700 Subject: [PATCH 5/5] add var name to error msg --- R/image-interact.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/R/image-interact.R b/R/image-interact.R index b2b1cf1fa..502b1fcf0 100644 --- a/R/image-interact.R +++ b/R/image-interact.R @@ -87,7 +87,7 @@ brushedPoints <- function(df, brush, xvar = NULL, yvar = NULL, if (is.null(xvar)) stop("brushedPoints: not able to automatically infer `xvar` from brush") if (!(xvar %in% names(df))) - stop("brushedPoints: `xvar` not in names of input") + stop("brushedPoints: `xvar` ('", xvar ,"') not in names of input") # Extract data values from the data frame x <- asNumber(df[[xvar]]) keep_rows <- keep_rows & (x >= brush$xmin & x <= brush$xmax) @@ -96,7 +96,7 @@ brushedPoints <- function(df, brush, xvar = NULL, yvar = NULL, if (is.null(yvar)) stop("brushedPoints: not able to automatically infer `yvar` from brush") if (!(yvar %in% names(df))) - stop("brushedPoints: `yvar` not in names of input") + stop("brushedPoints: `yvar` ('", yvar ,"') not in names of input") y <- asNumber(df[[yvar]]) keep_rows <- keep_rows & (y >= brush$ymin & y <= brush$ymax) } @@ -250,9 +250,9 @@ nearPoints <- function(df, coordinfo, xvar = NULL, yvar = NULL, stop("nearPoints: not able to automatically infer `yvar` from coordinfo") if (!(xvar %in% names(df))) - stop("nearPoints: `xvar` not in names of input") + stop("nearPoints: `xvar` ('", xvar ,"') not in names of input") if (!(yvar %in% names(df))) - stop("nearPoints: `yvar` not in names of input") + stop("nearPoints: `yvar` ('", yvar ,"') not in names of input") # Extract data values from the data frame x <- asNumber(df[[xvar]])