表在r中有多个子行,并写入到pdf。

时间:2021-03-26 22:57:05

Is it possible to generate a table in R with multiple rows correspondng to a single row? And write the resultant table to a pdf. The sample table is as below. 表在r中有多个子行,并写入到pdf。

是否可以在R中生成一个表,并将多个行对应到单个行?并将结果表写为pdf格式。示例表如下所示。

Is it possible to join two seperate tables in the way showed in the image. Sample code for the two tables are given below

是否可能以图像中显示的方式连接两个独立的表。下面给出了这两个表的示例代码

tab1="Test Description
1 test1 description
2 test2 description"
table1 <-read.table(text = tab1,header = TRUE)

tab21="Cause Probability Feedback
1 cause1 .5 positive
2 Cause2 .2 negative
3 Cause3 .1 negative
4 Cause4 .2 negative"
table2 <-read.table(text = tab21,header = TRUE)

tab22="Cause Probability Feedback
1 cause1 .7 positive
2 Cause2 .2 negative
3 Cause3 .1 negative"
table3 <-read.table(text = tab22,header = TRUE)

2 个解决方案

#1


2  

It is a little bit tricky, but I'd take advantage of the fact that cells with NAs are printed as empty by the print.xtable-function. The cells are not truly 'merged', but it looks like it when the contents are aligned to the top.

这有点棘手,但是我要利用这样一个事实,即带NAs的单元格在print.xtable函数中打印为空。单元格并不是真正的“合并”,但是当内容与顶部对齐时,它看起来就像合并了一样。

Basically the steps are:

基本步骤是:

  1. Generate a suitable data.frame in R
  2. 在R中生成一个合适的数据
  3. Print this as a .tex compatible table using print.xtable from the package 'xtable'
  4. 使用Print将其打印为.tex兼容表。来自包'xtable'的xtable
  5. Use Sweave/knitr/etc to generate a suitable .tex
  6. 使用Sweave/knitr/等来生成一个合适的。tex
  7. tools::texi2pdf will then convert your .tex to a suitable .pdf
  8. 工具::texi2pdf将会将您的.tex转换成合适的。pdf。

Here are the files, you need to only source the RunSweave.R in your R terminal (and make sure you have LaTeX installed along with the required packages, i.e. 'xtable and have the files in a single folder; this was run in Windows).

这里是文件,您只需要提供RunSweave的源代码。在您的R终端(并确保您已经安装了乳胶和所需的包,例如。'xtable,将文件放在一个文件夹中;这是在Windows中运行的)。

File StackExampleCode.R:

文件StackExampleCode.R:

# StackExampleCode.R
library(xtable)

# A work-around by setting rows in the multi-row to NA after the initial top-justified line
header <- data.frame(test = "Tests", det = "Details", cause = "Cause", prob = "Probability", fb = "Feedback")
# Filling the fields for these is something you'd probably want to do in R in a more sophisticated manner
test1 <- data.frame(
    test = c("Test 1", NA, NA, NA, NA),
    det = c("Description", NA, NA, NA, NA),
    cause = c("Cause 1", NA, paste("Cause", 2:4)),
    prob = c(".5", NA, ".2", ".1", ".2"),
    fb = c("positive", NA, "negative", "negative", "negative")
)
test2 <- data.frame(
    test = c("Test 2", NA, NA, NA),
    det = c("Description", NA, NA, NA),
    cause = c(paste("Cause", 1:3), NA),
    prob = c(".7", ".1", ".2", NA),
    fb = c("positive", "negative", "negative", NA)
)
# Bind it all together, you probably want something similar if it's automatic data you're generating
tab <- rbind(header, test1, test2)

File StackExampleRnw.Rnw:

文件StackExampleRnw.Rnw:

% StackExampleRnw.Rnw
% Note the different comment char, writing .tex here
\documentclass{article}

\begin{document}

<<echo=FALSE, results=tex>>=
# Printing the table
print(
    xtable(tab, 
        align = "|l|l|l|l|l|l|" # Create the desired vertical lines and text alignments ala LaTeX; left align with vertical lines in-between each column)
    ),
    add.to.row = list( # Add horizontal lines to correct spots, should be adjusted according to the desired data
        pos = list(-1, 1, 6, nrow(tab)), 
        command = c("\\hline \n", "\\hline \n", "\\hline \n", "\\hline \n") # Horizontal lines and a neater formatting of output using a linechange
    ),
    include.rownames = FALSE, # Don't include the rownames (which would be just numbers)
    include.colnames = FALSE, # Don't include the rownames, these were already included as if it was an ordinary table row
    hline.after = NULL # Suppress the empty horizontal line that is intended for an automated caption
)
@
\end{document}

File RunSweave.R:

文件RunSweave.R:

# RunSweave.R

# Run the code
source("StackExampleCode.R")
# Bundle R code with LaTeX
Sweave("StackExampleRnw.Rnw")
# .tex -> .pdf
tools::texi2pdf("StackExampleRnw.tex")

Here's what it looks like for me in StackExampleRnw.pdf:

这是我在stackexamplerneng网站上看到的。pdf:

表在r中有多个子行,并写入到pdf。

Alternatively, you can directly access the table in .tex in the file StackExampleRnw.tex and do some additional formatting if you're comfortable with it. Above doesn't require any additional tinkering in .tex, but you need to make sure you put the horizontal lines and NAs to correct places.

或者,您可以直接访问文件StackExampleRnw中的.tex中的表。特克斯,如果你喜欢,可以做一些额外的格式化。上面不需要在.tex中进行任何额外的修改,但是需要确保将水平线和NAs放在正确的位置。

If you're not comfortable with .tex, the print.xtable-function has plenty of parameters available for further formatting. If the partial horizontal lines are really important for you in the three columns to the right, I'd probably split this into two tables and then just glue them together horizontally and have the right one with a horizontal line in each row.

如果你不喜欢。tex,打印。xtable函数有很多参数可供进一步格式化。如果在右边的三列中,部分水平线对你来说非常重要,我很可能把它分成两个表,然后把它们水平地粘在一起,然后在每一行都有一个水平线。

#2


1  

I would have liked to accomplish this in pixiedust by merging some cells, but it appears I have a flaw in pixiedust that doesn't allow for vertical borders on merged rows. The workaround uses Teemu's approach of setting the cells we don't wish to view to NA and directing them to be printed as empty characters.

我本来希望通过合并一些单元来实现这一点,但是看来我在pixiedust中有一个缺陷,不允许在合并的行上有垂直的边界。解决方案使用Teemu的方法,将我们不希望查看的单元格设置为NA,并将它们作为空字符打印出来。

library(dplyr)
library(pixiedust)

table2$Test <- "test1"
table3$Test <- "test2"

bind_rows(
  right_join(table1, table2),
  right_join(table1, table3)
) %>%
  mutate(Description = as.character(Description)) %>%
  group_by(Test) %>%
  mutate(Description = ifelse(duplicated(Description), NA, Description)) %>%
  ungroup() %>%
  mutate(Test = ifelse(duplicated(Test), NA, Test))%>%
  dust(float = FALSE) %>%
  sprinkle(cols = 1:2,
           rows = c(4, 7),
           border = "bottom") %>%
  sprinkle(cols = 1:2,
           rows = 1,
           border = "top") %>%
  sprinkle(cols = 1:2, 
           border = "left",
           na.string = "") %>%
  medley_all_borders(cols = 3:5) %>%
  medley_all_borders(part = "head") %>%
  sprinkle_print_method("latex")

A full, working RMD file would be:

完整、有效的RMD文件将是:

---
title: "Untitled"
output: pdf_document
header-includes: 
- \usepackage{amssymb} 
- \usepackage{arydshln} 
- \usepackage{caption} 
- \usepackage{graphicx} 
- \usepackage{hhline} 
- \usepackage{longtable} 
- \usepackage{multirow} 
- \usepackage[dvipsnames,table]{xcolor} 

---

```{r, echo = FALSE, message = FALSE, warning = FALSE}
library(dplyr)
library(pixiedust)

tab1="Test Description
1 test1 description
2 test2 description"
table1 <-read.table(text = tab1,header = TRUE)

tab21="Cause Probability Feedback
1 cause1 .5 positive
2 Cause2 .2 negative
3 Cause3 .1 negative
4 Cause4 .2 negative"
table2 <-read.table(text = tab21,header = TRUE)

tab22="Cause Probability Feedback
1 cause1 .7 positive
2 Cause2 .2 negative
3 Cause3 .1 negative"
table3 <-read.table(text = tab22,header = TRUE)
```

```{r, echo = FALSE, message = FALSE, warning = FALSE}
table2$Test <- "test1"
table3$Test <- "test2"

bind_rows(
  right_join(table1, table2),
  right_join(table1, table3)
) %>%
  mutate(Description = as.character(Description)) %>%
  group_by(Test) %>%
  mutate(Description = ifelse(duplicated(Description), NA, Description)) %>%
  ungroup() %>%
  mutate(Test = ifelse(duplicated(Test), NA, Test))%>%
  dust(float = FALSE) %>%
  sprinkle(cols = 1:2,
           rows = c(4, 7),
           border = "bottom") %>%
  sprinkle(cols = 1:2,
           rows = 1,
           border = "top") %>%
  sprinkle(cols = 1:2, 
           border = "left",
           na.string = "") %>%
  medley_all_borders(cols = 3:5) %>%
  medley_all_borders(part = "head")
```

#1


2  

It is a little bit tricky, but I'd take advantage of the fact that cells with NAs are printed as empty by the print.xtable-function. The cells are not truly 'merged', but it looks like it when the contents are aligned to the top.

这有点棘手,但是我要利用这样一个事实,即带NAs的单元格在print.xtable函数中打印为空。单元格并不是真正的“合并”,但是当内容与顶部对齐时,它看起来就像合并了一样。

Basically the steps are:

基本步骤是:

  1. Generate a suitable data.frame in R
  2. 在R中生成一个合适的数据
  3. Print this as a .tex compatible table using print.xtable from the package 'xtable'
  4. 使用Print将其打印为.tex兼容表。来自包'xtable'的xtable
  5. Use Sweave/knitr/etc to generate a suitable .tex
  6. 使用Sweave/knitr/等来生成一个合适的。tex
  7. tools::texi2pdf will then convert your .tex to a suitable .pdf
  8. 工具::texi2pdf将会将您的.tex转换成合适的。pdf。

Here are the files, you need to only source the RunSweave.R in your R terminal (and make sure you have LaTeX installed along with the required packages, i.e. 'xtable and have the files in a single folder; this was run in Windows).

这里是文件,您只需要提供RunSweave的源代码。在您的R终端(并确保您已经安装了乳胶和所需的包,例如。'xtable,将文件放在一个文件夹中;这是在Windows中运行的)。

File StackExampleCode.R:

文件StackExampleCode.R:

# StackExampleCode.R
library(xtable)

# A work-around by setting rows in the multi-row to NA after the initial top-justified line
header <- data.frame(test = "Tests", det = "Details", cause = "Cause", prob = "Probability", fb = "Feedback")
# Filling the fields for these is something you'd probably want to do in R in a more sophisticated manner
test1 <- data.frame(
    test = c("Test 1", NA, NA, NA, NA),
    det = c("Description", NA, NA, NA, NA),
    cause = c("Cause 1", NA, paste("Cause", 2:4)),
    prob = c(".5", NA, ".2", ".1", ".2"),
    fb = c("positive", NA, "negative", "negative", "negative")
)
test2 <- data.frame(
    test = c("Test 2", NA, NA, NA),
    det = c("Description", NA, NA, NA),
    cause = c(paste("Cause", 1:3), NA),
    prob = c(".7", ".1", ".2", NA),
    fb = c("positive", "negative", "negative", NA)
)
# Bind it all together, you probably want something similar if it's automatic data you're generating
tab <- rbind(header, test1, test2)

File StackExampleRnw.Rnw:

文件StackExampleRnw.Rnw:

% StackExampleRnw.Rnw
% Note the different comment char, writing .tex here
\documentclass{article}

\begin{document}

<<echo=FALSE, results=tex>>=
# Printing the table
print(
    xtable(tab, 
        align = "|l|l|l|l|l|l|" # Create the desired vertical lines and text alignments ala LaTeX; left align with vertical lines in-between each column)
    ),
    add.to.row = list( # Add horizontal lines to correct spots, should be adjusted according to the desired data
        pos = list(-1, 1, 6, nrow(tab)), 
        command = c("\\hline \n", "\\hline \n", "\\hline \n", "\\hline \n") # Horizontal lines and a neater formatting of output using a linechange
    ),
    include.rownames = FALSE, # Don't include the rownames (which would be just numbers)
    include.colnames = FALSE, # Don't include the rownames, these were already included as if it was an ordinary table row
    hline.after = NULL # Suppress the empty horizontal line that is intended for an automated caption
)
@
\end{document}

File RunSweave.R:

文件RunSweave.R:

# RunSweave.R

# Run the code
source("StackExampleCode.R")
# Bundle R code with LaTeX
Sweave("StackExampleRnw.Rnw")
# .tex -> .pdf
tools::texi2pdf("StackExampleRnw.tex")

Here's what it looks like for me in StackExampleRnw.pdf:

这是我在stackexamplerneng网站上看到的。pdf:

表在r中有多个子行,并写入到pdf。

Alternatively, you can directly access the table in .tex in the file StackExampleRnw.tex and do some additional formatting if you're comfortable with it. Above doesn't require any additional tinkering in .tex, but you need to make sure you put the horizontal lines and NAs to correct places.

或者,您可以直接访问文件StackExampleRnw中的.tex中的表。特克斯,如果你喜欢,可以做一些额外的格式化。上面不需要在.tex中进行任何额外的修改,但是需要确保将水平线和NAs放在正确的位置。

If you're not comfortable with .tex, the print.xtable-function has plenty of parameters available for further formatting. If the partial horizontal lines are really important for you in the three columns to the right, I'd probably split this into two tables and then just glue them together horizontally and have the right one with a horizontal line in each row.

如果你不喜欢。tex,打印。xtable函数有很多参数可供进一步格式化。如果在右边的三列中,部分水平线对你来说非常重要,我很可能把它分成两个表,然后把它们水平地粘在一起,然后在每一行都有一个水平线。

#2


1  

I would have liked to accomplish this in pixiedust by merging some cells, but it appears I have a flaw in pixiedust that doesn't allow for vertical borders on merged rows. The workaround uses Teemu's approach of setting the cells we don't wish to view to NA and directing them to be printed as empty characters.

我本来希望通过合并一些单元来实现这一点,但是看来我在pixiedust中有一个缺陷,不允许在合并的行上有垂直的边界。解决方案使用Teemu的方法,将我们不希望查看的单元格设置为NA,并将它们作为空字符打印出来。

library(dplyr)
library(pixiedust)

table2$Test <- "test1"
table3$Test <- "test2"

bind_rows(
  right_join(table1, table2),
  right_join(table1, table3)
) %>%
  mutate(Description = as.character(Description)) %>%
  group_by(Test) %>%
  mutate(Description = ifelse(duplicated(Description), NA, Description)) %>%
  ungroup() %>%
  mutate(Test = ifelse(duplicated(Test), NA, Test))%>%
  dust(float = FALSE) %>%
  sprinkle(cols = 1:2,
           rows = c(4, 7),
           border = "bottom") %>%
  sprinkle(cols = 1:2,
           rows = 1,
           border = "top") %>%
  sprinkle(cols = 1:2, 
           border = "left",
           na.string = "") %>%
  medley_all_borders(cols = 3:5) %>%
  medley_all_borders(part = "head") %>%
  sprinkle_print_method("latex")

A full, working RMD file would be:

完整、有效的RMD文件将是:

---
title: "Untitled"
output: pdf_document
header-includes: 
- \usepackage{amssymb} 
- \usepackage{arydshln} 
- \usepackage{caption} 
- \usepackage{graphicx} 
- \usepackage{hhline} 
- \usepackage{longtable} 
- \usepackage{multirow} 
- \usepackage[dvipsnames,table]{xcolor} 

---

```{r, echo = FALSE, message = FALSE, warning = FALSE}
library(dplyr)
library(pixiedust)

tab1="Test Description
1 test1 description
2 test2 description"
table1 <-read.table(text = tab1,header = TRUE)

tab21="Cause Probability Feedback
1 cause1 .5 positive
2 Cause2 .2 negative
3 Cause3 .1 negative
4 Cause4 .2 negative"
table2 <-read.table(text = tab21,header = TRUE)

tab22="Cause Probability Feedback
1 cause1 .7 positive
2 Cause2 .2 negative
3 Cause3 .1 negative"
table3 <-read.table(text = tab22,header = TRUE)
```

```{r, echo = FALSE, message = FALSE, warning = FALSE}
table2$Test <- "test1"
table3$Test <- "test2"

bind_rows(
  right_join(table1, table2),
  right_join(table1, table3)
) %>%
  mutate(Description = as.character(Description)) %>%
  group_by(Test) %>%
  mutate(Description = ifelse(duplicated(Description), NA, Description)) %>%
  ungroup() %>%
  mutate(Test = ifelse(duplicated(Test), NA, Test))%>%
  dust(float = FALSE) %>%
  sprinkle(cols = 1:2,
           rows = c(4, 7),
           border = "bottom") %>%
  sprinkle(cols = 1:2,
           rows = 1,
           border = "top") %>%
  sprinkle(cols = 1:2, 
           border = "left",
           na.string = "") %>%
  medley_all_borders(cols = 3:5) %>%
  medley_all_borders(part = "head")
```