How to combine row and column layout in flexdashbo

2019-01-22 03:20发布

问题:

For a new project I want to try the new flexdasboard package. I am thinking of a lay out in which the column and row orientation is somehow combined.

The layout I am thinking of is something like this:

If I change this code:

---
title: "Focal Chart (Left)"
output: flexdashboard::flex_dashboard
---

Column {data-width=600}
-------------------------------------

### Chart 1

```{r}
```

Column {data-width=400}
-------------------------------------

### Chart 2

```{r}
```   

### Chart 3

```{r}
```

into this:

---
title: "Focal Chart (Left)"
output: flexdashboard::flex_dashboard
---

Column {data-width=600}
-------------------------------------

### Chart 1

```{r}
```

Column {data-width=400}
-------------------------------------

Row {data-width=400}
-------------------------------------

### Chart 2

```{r}
```   

### Chart 3

```{r}
```   

Row {data-width=400}
-------------------------------------

### Chart 4

```{r}
```

(ofcourse) this doesn't work, but I haven't figured out the right way. Does anyone have an idea?

回答1:

This does not seem possible using basic rows and columns, but can be achieved by using a sidebar to hold the content of the left hand panel. This will change the formatting of the left panel compared to the others, but its appearance can then be adusted to your liking by editing the css. Note that you can alter the width of the side bar using the data-width option e.g. {.sidebar data-width=300}

---
title: "Focal Chart"
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
---

Column {.sidebar data-width=500}
-------------------------------------
### Chart 1
```{r}
```

Row {data-height=350}
-------------------------------------
### Chart 2
```{r}
```

### Chart 3
```{r}
```   

Row {data-height=650}
-------------------------------------
### Chart 4
```{r}
```

Which gives...

The appearance of the side bar can then be edited to your liking. For example:

To

  1. change the background color of the side panel to white (if you want it to match the other panels),
  2. align the top edge with the other panels, and
  3. add borders left and bottom to match the other panels:

edit the css style sheet for .section.sidebar to

.section.sidebar {
  top: 61px;
  border-bottom: 10px solid #ececec;
  border-left: 10px solid #ececec;
  background-color: rgba(255, 255, 255, 1);
}

To change the padding, use the data-padding option in flexdashboard markdown:

Column {.sidebar data-width=500 data-padding=10}

Now, it looks like this:



回答2:

What you really need is the fillCol and fillRow functions. Take a look at this: http://shiny.rstudio.com/articles/gadget-ui.html#fillrowfillcol



回答3:

I composed this flexdashboard example from what I found in the Shiny+flex site in RStudio using fillCol:

---
title: "Fill Layout"
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
runtime: shiny
---

# Info {.sidebar data-width=350}

When you mix multiple Shiny inputs and/or outputs within a flexdashboard panel it’s good practice to have them fill the bounds of their container in the same way that other flexdashboard components like plots and htmlwidgets do. This is possible using the Shiny `fillRow` and `fillCol` layout functions.

For those familiar with Shiny here are further details on how this example works:

1. The container is laid out using the `fillCol` function, which establishes a single column layout with flexible row heights.

2. Flexible height behavior is defined via `flex = c(NA, 1)`. The `NA` applies to the first component (the input panel) and says to not give it flexible height (i.e. allow it to occupy it’s natural height). The `1` applies to the second component (the plot) and says that it should have flexible height (i.e. occupy all remaining height in the container).

3. The call to `plotOutput` includes `height = "100%"` to ensure that the plot takes advantage of the height allocated to it by the `fillCol` flexible layout.

4. Finally, note that unlike the simpler layout examples above this examples uses an explicit  `plotOutput` / `renderPlot` pairing rather than just a standalone `renderPlot`. This is so that the plot can be included in a more sophisticated layout scheme (i.e. one more like traditional ui.R layout).

# Use fillCol

```{r}
fillCol(height = 600, flex = c(NA, 1), 
  inputPanel(
    selectInput("region", "Region:", choices = colnames(WorldPhones))
  ),
  plotOutput("phonePlot", height = "100%")
)

output$phonePlot <- renderPlot({
  barplot(WorldPhones[,input$region]*1000, 
          ylab = "Number of Telephones", xlab = "Year")
})
```


回答4:

An alternative approach can be to use absolutepanels from shiny. Instead of trying to find a grid arrangement to fit all the pieces on screen, use an absolutepanel with folding buttons to selectively choose which boxes appear at a given time. This allows the user to choose which plots and information they want presented. The idea evolved from the superzip app https://shiny.rstudio.com/gallery/superzip-example.html, but works well in flexdashboard.

In the example below, plots can be made to appear or be hidden when the page loads. Click the buttons to make them appear or go away. This has been very useful when mixing leaflet with plots, to avoid drowning the map with plots (where as before plots were limited due to drowning issues).

---
  title: "Demo"
  output:
    flexdashboard::flex_dashboard:
      orientation: columns
      vertical_layout: fill
  ---


  ```{r setup, include=FALSE}
  library(flexdashboard)
  library(rmarkdown)
  library(plotly)
  library(shiny)

  ```

  Column {data-width=400}
  --------------------------------
  ### Planet Earth

  ```{r}

  library(leaflet)
  m = leaflet() %>% addTiles()
  m  # a map with the default OSM tile layer


  ```


  ```{r}
  #plot setup
  mtcars$am[which(mtcars$am == 0)] <- 'Automatic'
  mtcars$am[which(mtcars$am == 1)] <- 'Manual'
  mtcars$am <- as.factor(mtcars$am)

  p <- plot_ly(mtcars, x = ~wt, y = ~hp, z = ~qsec, color = ~am, colors = c('#BF382A', '#0C4B8E')) %>%
    add_markers() %>%
    layout(scene = list(xaxis = list(title = 'Weight'),
                       yaxis = list(title = 'Gross horsepower'),
                       zaxis = list(title = '1/4 mile time')))


  set.seed(100)
  d <- diamonds[sample(nrow(diamonds), 1000), ]


  ##########################
  absolutePanel(id = "controls", class = "panel panel-default", fixed = TRUE,
                draggable = TRUE, top = 70, left = "auto", right = 20, bottom = "auto",
                width = '30%', height = 'auto', 
                style = "overflow-y:scroll; max-height: 1000px; opacity: 0.9; style = z-index: 400",

              h4(strong("Plot Explorer")),

      HTML('<button data-toggle="collapse" data-target="#box1" class="btn-block btn-primary">dot plot</button>'),
      tags$div(id = 'box1', class="collapse in",

        plot_ly(d, x = ~carat, y = ~price, color = ~carat,
          size = ~carat, text = ~paste("Clarity: ", clarity)) %>% layout(height=200)

              ),

   HTML('<button data-toggle="collapse" data-target="#box2" class="btn-block btn-warning">histogram</button>'),
      tags$div(id = 'box2', class="collapse",

         plot_ly(x = rnorm(500), type = "histogram", name = "Histogram") %>% layout(height=200)
      ),


           HTML('<button data-toggle="collapse" data-target="#box3" class="btn-block btn-danger">spinny thing</button>'),
      tags$div(id = 'box3', class="collapse in",

          p %>% layout(height=200)
      )

   )

  ```