使用markdown,rstudio和knitr在表格中对齐图像

时间:2016-07-24 17:56:44

标签: r rstudio knitr r-markdown

我正在尝试使用Rstudio创建PDF格式工作的标准月度报告,我想将ggplot输出与图表相结合 - 一个新图表,每行一个单元格。我是markdown,latex,pandoc和knitr的新手,所以这对我来说是一个雷区。

我已经找到了如何使用kable插入图表,但图像未与同一行的文本对齐。

我在问题的底部使用虚拟数据放了一些(rstudio markdown)代码,这里有一些图片显示了我正在尝试做的事情以及我遇到的问题

Example of graphic I want to incorporate into table

This is what the table looks like with the misaligned text and images

您可以看到文本和图像未对齐。如果我把图像留下来,表格很好而且紧凑,将图像放在一起意味着桌子分布在多个页面上,即使图像本身并不高。

任何欢迎的建议 - 代码片段加倍。

非常感谢

  title: "Untitled"
  output: pdf_document
  ---

  This example highlights the issue I'm having with formatting a nice table with the graphics and the vertical alignment of text.



  ```{r echo=FALSE, results='hide', warning=FALSE, message=FALSE}
    ## Load modules
    library(dplyr)
    library(tidyr)
    library(ggplot2)

    ## Create a local function to plot the z score
    varianceChart <- function(df, personNumber) {
      plot <- df %>%
        filter(n == personNumber) %>%
        ggplot() +
        aes(x=zscore, y=0) +
        geom_rect(aes(xmin=-3.32, xmax=-1.96, ymin=-1, ymax=1), fill="orange2", alpha=0.8) + 
        geom_rect(aes(xmin=1.96, xmax=3.32, ymin=-1, ymax=1), fill="olivedrab3", alpha=0.8) +
        geom_rect(aes(xmin=min(-4, zscore), xmax=-3.32, ymin=-1, ymax=1), fill="orangered3") + 
        geom_rect(aes(xmin=3.32, xmax=max(4, zscore), ymin=-1, ymax=1), fill="chartreuse4") +
        theme(axis.title = element_blank(), 
              axis.ticks = element_blank(), 
              axis.text = element_blank(),
              panel.grid.minor = element_blank(),
              panel.grid.major = element_blank()) +
        geom_vline(xintercept=0, colour="black", alpha=0.3) +
        geom_point(size=15, shape=4, fill="lightblue") ##Cross looks better than diamond

      return(plot)
    }

    ## Create dummy data
    Person1 <- rnorm(1, mean=10, sd=2) 
    Person2 <- rnorm(1, mean=10, sd=2)
    Person3 <- rnorm(1, mean=10, sd=2)
    Person4 <- rnorm(1, mean=10, sd=2) 
    Person5 <- rnorm(1, mean=10, sd=2) 
    Person6 <- rnorm(1, mean=6,  sd=1) 

    ## Add to data frame
    df <- data.frame(Person1, Person2, Person3, Person4, Person5, Person6)

    ## Bring all samples into one column and then calculate stats
    df2 <- df %>% 
      gather(key=Person, value=time)

    mean <- mean(df2$time)
    sd   <- sqrt(var(df2$time))

    stats <- df2 %>%
      mutate(n = row_number()) %>%
      group_by(Person) %>%
      mutate(zscore = (time - mean) / sd)

    graph_directory <- getwd() #'./Graphs'

    ## Now to cycle through each Person and create a graph
    for(i in seq(1, nrow(stats))) {
      print(i)
      varianceChart(stats, i)

      ggsave(sprintf("%s/%s.png", graph_directory, i), plot=last_plot(), units="mm", width=50, height=10, dpi=1200)
    }

    ## add a markup reference to this dataframe
    stats$varianceChart <- sprintf('![](%s/%s.png)', graph_directory, stats$n)  

    df.table <- stats[, c(1,2,5)]
    colnames(df.table) <- c("Person Name", "Time taken", "Variance Chart")
  ```


  ```{r}  
    library(knitr)
    kable(df.table[, c(1,2)], caption="Rows look neat and a sensible distance apart")
    kable(df.table, caption="Rows are separated a long way apart and images and text are misaligned")

  ```

2 个答案:

答案 0 :(得分:0)

考虑使用LaTeX:

enter image description here

请注意\\includegraphics行。您也可以尝试(注释掉)线调整绘图边距。

\documentclass{article}
\usepackage{graphicx}

\begin{document}

  This example highlights the issue I'm having with formatting a nice table with the graphics and the vertical alignment of text.



<<preamble, echo=FALSE, results='hide', warning=FALSE, message=FALSE>>=
## Load modules
library(dplyr)
library(tidyr)
library(ggplot2)

## Create a local function to plot the z score
varianceChart <- function(df, personNumber) {
  plot <- df %>%
    filter(n == personNumber) %>%
    ggplot() +
    aes(x=zscore, y=0) +
    geom_rect(aes(xmin=-3.32, xmax=-1.96, ymin=-1, ymax=1), fill="orange2", alpha=0.8) + 
    geom_rect(aes(xmin=1.96, xmax=3.32, ymin=-1, ymax=1), fill="olivedrab3", alpha=0.8) +
    geom_rect(aes(xmin=min(-4, zscore), xmax=-3.32, ymin=-1, ymax=1), fill="orangered3") + 
    geom_rect(aes(xmin=3.32, xmax=max(4, zscore), ymin=-1, ymax=1), fill="chartreuse4") +
    theme(axis.title = element_blank(), 
          axis.ticks = element_blank(), 
          axis.text = element_blank(),
          panel.grid.minor = element_blank(),
          panel.grid.major = element_blank() 
          #,plot.margin = margin(0, 0, 0, 0, "lines")
    ) +
    geom_vline(xintercept=0, colour="black", alpha=0.3) +
    geom_point(size=15, shape=4, fill="lightblue") ##Cross looks better than diamond

  return(plot)
}

## Create dummy data
Person1 <- rnorm(1, mean=10, sd=2) 
Person2 <- rnorm(1, mean=10, sd=2)
Person3 <- rnorm(1, mean=10, sd=2)
Person4 <- rnorm(1, mean=10, sd=2) 
Person5 <- rnorm(1, mean=10, sd=2) 
Person6 <- rnorm(1, mean=6,  sd=1) 

## Add to data frame
df <- data.frame(Person1, Person2, Person3, Person4, Person5, Person6)

## Bring all samples into one column and then calculate stats
df2 <- df %>% 
  gather(key=Person, value=time)

mean <- mean(df2$time)
sd   <- sqrt(var(df2$time))

stats <- df2 %>%
  mutate(n = row_number()) %>%
  group_by(Person) %>%
  mutate(zscore = (time - mean) / sd)

graph_directory <- getwd() #'./Graphs'

## Now to cycle through each Person and create a graph
for(i in seq(1, nrow(stats))) {
  print(i)
  varianceChart(stats, i)

  ggsave(sprintf("%s/%s.pdf", graph_directory, i), plot=last_plot(), units="mm", width=50, height=10, dpi=1200)
}

## add a markup reference to this dataframe
stats$varianceChart <- sprintf('\\begin{tabular}{l}\\relax \\includegraphics{%s/%s.pdf} \\end{tabular}', graph_directory, stats$n)  

df.table <- stats[, c(1,2,5)]
colnames(df.table) <- c("Person Name", "Time taken", "Variance Chart")
@


<<tables, results='asis'>>= 
library(knitr)
library(xtable)
print.xtable(xtable(df.table[, c(1,2)], caption="Rows look neat and a sensible distance apart"), sanitize.text.function = function(x){x})
print.xtable(xtable(df.table, caption="Rows are separated a long way apart and images and text are misaligned"), sanitize.text.function = function(x){x})
@

\end{document}

答案 1 :(得分:0)

或者您使用\raisebox。它将内容放在一个新框中,并使用其参数修改框的偏移量(使用当前设置为-0.4的参数进行播放):

---
title: "Untitled"
output: pdf_document
---

This example highlights the issue I am having with formatting a nice table with the graphics and the vertical alignment of text.

```{r echo=FALSE, results='hide', warning=FALSE, message=FALSE}
## Load modules
library(dplyr)
library(tidyr)
library(ggplot2)

## Create a local function to plot the z score
varianceChart <- function(df, personNumber) {
  plot <- df %>%
             filter(n == personNumber) %>%
             ggplot() +
             aes(x=zscore, y=0) +
             geom_rect(aes(xmin=-3.32, xmax=-1.96, ymin=-1, ymax=1), fill="orange2", alpha=0.8) + 
             geom_rect(aes(xmin=1.96, xmax=3.32, ymin=-1, ymax=1), fill="olivedrab3", alpha=0.8) +
             geom_rect(aes(xmin=min(-4, zscore), xmax=-3.32, ymin=-1, ymax=1), fill="orangered3") + 
             geom_rect(aes(xmin=3.32, xmax=max(4, zscore), ymin=-1, ymax=1), fill="chartreuse4") +
             theme(axis.title = element_blank(), 
                   axis.ticks = element_blank(), 
                   axis.text = element_blank(),
                   panel.grid.minor = element_blank(),
                   panel.grid.major = element_blank()) +
                   geom_vline(xintercept=0, colour="black", alpha=0.3) +
                   geom_point(size=15, shape=4, fill="lightblue") ##Cross looks better than diamond
  return(plot)
}

## Create dummy data
Person1 <- rnorm(1, mean=10, sd=2) 
Person2 <- rnorm(1, mean=10, sd=2)
Person3 <- rnorm(1, mean=10, sd=2)
Person4 <- rnorm(1, mean=10, sd=2) 
Person5 <- rnorm(1, mean=10, sd=2) 
Person6 <- rnorm(1, mean=6,  sd=1) 

## Add to data frame
df <- data.frame(Person1, Person2, Person3, Person4, Person5, Person6)

## Bring all samples into one column and then calculate stats
df2  <- df %>% gather(key=Person, value=time)
mean <- mean(df2$time)
sd   <- sqrt(var(df2$time))

stats <- df2 %>%
             mutate(n = row_number()) %>%
             group_by(Person) %>%
             mutate(zscore = (time - mean) / sd)

graph_directory <- getwd() #'./Graphs'

## Now to cycle through each Person and create a graph
for(i in seq(1, nrow(stats))) {
  print(i)
  varianceChart(stats, i)

  ggsave(sprintf("%s/%s.png", graph_directory, i), plot=last_plot(), units="mm", width=100, height=20, dpi=1200)
}

## add a markup reference to this dataframe
stats$varianceChart <- sprintf('\\raisebox{-.4\\totalheight}{\\includegraphics[width=0.2\\textwidth, height=20mm]{%s/%s.png}}', graph_directory, stats$n) 

df.table <- stats[, c(1,2,5)]
colnames(df.table) <- c("Person Name", "Time taken", "Variance Chart")
```

```{r}
library(knitr)
kable(df.table[, c(1,2)], caption="Rows look neat and a sensible distance apart")
kable(df.table, caption="Rows are separated a long way apart and images and text are misaligned")
```

enter image description here