PavoDive
PavoDive

Reputation: 6496

passing shiny variable to data.table

I'm struggling with a flexdashboard as I can't find a way to pass a variable name to data.table.

I've gone through How can one work fully generically in data.table in R with column names in variables and all referenced questions, also Use data.table within another function in R and many similar ones, trying get, mget, .., eval to no avail (I've tried with = FALSE and with = TRUE too).

The reproducible example and what I've already tried is in the .Rmd file that follows:

---
title: "Untitled"
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: fill
  runtime: shiny
---

```{r setup, include=FALSE}
library(flexdashboard)
library(data.table)
library(ggplot2)
library(shiny)
```

```{r, include = FALSE}
a <- data.table(x = c(1, 1, 2, 3), y = c(1, 2, 3, 3), z = c(1, 2, 2, 3))
```

Column {.sidebar, data-width=75}
-----------------------------------------------------------------------

```{r}
selectInput("varname", label = "tell me the variable", choices = c("x", "y", "z"), selected = "z")
```

Column
-----------------------------------------------------------------------

### when in the "by", it works

```{r}
renderPlot({ggplot(a[, sum(x), by = c(input$varname)], aes(x = get(input$varname), y = V1))+geom_line()})
```

### varname

```{r}
renderPrint(input$varname)
```

### vector

```{r}
renderPrint(a[, get(input$varname)])
```

### Now this fails: with get (either with = FALSE or = TRUE)

```{r}
renderPlot({ggplot(a[, sum(get(input$varname)), by = z], aes(x = z, y = get(input$varname)))+geom_point()})
```

Column
--------------------

### with c

```{r}
renderPlot({ggplot(a[, sum(c(input$varname)), by = z, with = FALSE], aes(x = z, y = get(input$varname)))+geom_point()})
```

### With mget

```{r}
renderPlot({ggplot(a[, sum(mget(input$varname)), by = z, with = FALSE], aes(x = z, y = get(input$varname)))+geom_point()})
```

### with eval

```{r}
renderPlot({ggplot(a[, sum(eval(input$varname)), by = z], aes(x = z, y = get(input$varname)))+geom_point()})
```

### with ..

```{r}
renderPlot({ggplot(a[, sum(..input$varname), by = z], aes(x = z, y = get(input$varname)))+geom_point()})
```

How can I achieve the plot I'm attempting?

EDIT:

I'm getting

Upvotes: 0

Views: 248

Answers (1)

chinsoon12
chinsoon12

Reputation: 25208

A possible approach:

---
title: "Untitled"
output:
    flexdashboard::flex_dashboard:
    orientation: columns
vertical_layout: fill
runtime: shiny
---

```{r setup, include=FALSE}
library(flexdashboard)
library(data.table)
library(ggplot2)
library(shiny)
```

```{r, include = FALSE}
a <- data.table(A=c(1, 1, 2, 3), B=c(1, 2, 3, 3), C=c(1, 2, 2, 3))
```

Column {.sidebar, data-width=75}
-----------------------------------------------------------------------

```{r}
selectInput("var_x", label="the x variable", choices=c("A", "B", "C"), selected="A")
selectInput("var_y", label="y variable to be summed", choices=c("A", "B", "C"), selected="C")
```

Column
-----------------------------------------------------------------------

### proposal

```{r}
renderPlot({
    ggplot(a[, sum(get(input$var_y)), by=eval(input$var_x)], aes(x=get(input$var_x), y=V1)) +
        geom_line()
})
```

Fix is basically to follow what is mentioned in the data.table error message:

Error: 'by' appears to evaluate to column names but isn't c() or key(). Use by=list(...) if you can. Otherwise, by=eval((input$var_x)) should work. This is for efficiency so data.table can detect which columns are needed

Upvotes: 1

Related Questions