Criação programática de tabelas Markdown em R com KnitR

103

Estou começando a aprender sobre o KnitR e o uso do Markdown na geração de documentos e relatórios R. Isso parece ser perfeito para muitas das reportagens do dia a dia que tenho a ver com meu trabalho. No entanto, uma coisa que não estou vendo é uma maneira fácil de imprimir quadros de dados e tabelas usando a formatação Markdown (mais ou menos como xtable, mas com Markdown em vez de LaTeX ou HTML). Eu sei que posso simplesmente incorporar a saída HTML de xtable, mas gostaria de saber se há alguma solução baseada em Markdown?

TARehman
fonte
3
Considerando xtable e html .. Imprima código html com print(xtable(data), type = "html").
user974514
7
@TARehman Sua pergunta me lembrou que ainda não havia uma solução que produzisse tabelas diretamente compatíveis knitr, então enviei uma solicitação de pull panderpara adicionar o estilo de tabela. Em versões futuras de pander, você deve ser capaz de fazerpandoc.table(iris, style="rmarkdown")
Marius
1
@Marius Por acaso você sabe por que o Pandoc não faz parte do CRAN? Ou quando pode se tornar parte dela? Apenas curioso.
TARehman
2
@TARehman Não tenho certeza se você quis dizer pander ou pandoc. panderdeve estar no CRAN. pandoc é um programa escrito em Haskell que converte de e para uma ampla variedade de formatos diferentes, não é específico do R de forma alguma.
Marius
1
Desculpe, eu quis dizer pander, que não estava no CRAN da última vez que ouvi - não pandoc. Minha culpa. :)
TARehman

Respostas:

122

Agora knitr(desde a versão 1.3) o pacote inclui a kablefunção para tabelas de criação:

> library(knitr)
> kable(head(iris[,1:3]), format = "markdown")
|  Sepal.Length|  Sepal.Width|  Petal.Length|
|-------------:|------------:|-------------:|
|           5,1|          3,5|           1,4|
|           4,9|          3,0|           1,4|
|           4,7|          3,2|           1,3|
|           4,6|          3,1|           1,5|
|           5,0|          3,6|           1,4|
|           5,4|          3,9|           1,7|

ATUALIZADO : se você obtiver marcação bruta em um documento, tente a results = "asis"opção de configuração do bloco.

Artem Klevtsov
fonte
24
ao executar dentro do knitr, você pode deixar o formatargumento de fora , já que o knitr está ciente do formato de saída e irá configurá-lo automaticamente
Yihui Xie
3
@Yihui Você é incrível
isomorfismos
2
Eu tentei isso, mas `` `{r} kable (...) apenas mostra a redução bruta
Alex Brown
6
Tente definir a opção de bloco local para results = asis.
Artem Klevtsov
5
O knitr para conhecimento agora requer o comando no formatoresults = 'asis'
Stedy
32

Dois pacotes que farão isso são pander

library(devtools)
install_github('pander', 'Rapporter')

Ou ascii

pander é uma abordagem ligeiramente diferente para a construção de relatórios (mas pode ser útil para esse recurso).

asciipermitirá que você printcom type = 'pandoc(ou vários outros sabores de marcação)

library(ascii)
print(ascii(head(iris[,1:3])), type = 'pandoc')



    **Sepal.Length**   **Sepal.Width**   **Petal.Length**  
--- ------------------ ----------------- ------------------
1   5.10               3.50              1.40              
2   4.90               3.00              1.40              
3   4.70               3.20              1.30              
4   4.60               3.10              1.50              
5   5.00               3.60              1.40              
6   5.40               3.90              1.70              
--- ------------------ ----------------- ------------------

Observe que, em ambos os casos, ele é direcionado ao uso pandocpara converter do markdown para o tipo de documento desejado; no entanto, o uso style='rmarkdown'criará tabelas que são compatíveis com este markdownpacote e a conversão embutida em rstudio.

mnel
fonte
3
Só uma observação sobre pander: pode produzir as rmarkdownmesas estilizadas também ao lado de outras, por exemplo:pander(head(iris[,1:3]), style = 'rmarkdown')
daroczig 09/11/2013
@daroczig - Obrigado e anotado na resposta agora,
mnel de
26

Só queria atualizar isso com o que decidi fazer. Estou usando o hwriterpacote agora para imprimir tabelas e usando os recursos row.*e col.*para colocar classes CSS em diferentes elementos. Então, escrevi CSS customizado para fazer minha exibição como eu queria. Então, aqui está um exemplo caso alguém esteja lidando com algo semelhante.

Primeiro, crie um arquivo que fará knittinge transformará o Markdown em HTML:

FILE: file_knit.r
#!/usr/bin/env Rscript

library(knitr)
library(markdown)

knit("file.Rmd")
markdownToHTML("file.md","file.html",stylesheet="~/custom.css")

Em seguida, crie o arquivo Markdown real:

FILE: file.Rmd
Report of Fruit vs. Animal Choices
==================================

This is a report of fruit vs. animal choices.

```{r echo=FALSE,results='asis'}
library(hwriter)
set.seed(9850104)
my.df <- data.frame(Var1=sample(x=c("Apple","Orange","Banana"),size=40,replace=TRUE),
                    Var2=sample(x=c("Dog","Cat","Bunny"),size=40,replace=TRUE))

tbl1 <- table(my.df$Var1,my.df$Var2)

tbl1 <- cbind(tbl1,rowSums(tbl1))
tbl1 <- rbind(tbl1,colSums(tbl1))

colnames(tbl1)[4] <- "TOTAL"
rownames(tbl1)[4] <- "TOTAL"

# Because I used results='asis' for this chunk, I can just use cat() and hwrite() to 
# write out the table in HTML. Using hwrite()'s row.* function, I can assign classes
# to the various table elements.
cat(hwrite(tbl1,
           border=NA,
           table.class="t1",
           row.class=list(c("header col_first","header col","header col","header col", "header col_last"),
                          c("col_first","col","col","col","col_last"),
                          c("col_first","col","col","col","col_last"),
                          c("col_first","col","col","col","col_last"),
                          c("footer col_first","footer col","footer col","footer col","footer col_last"))))
```

Finalmente, basta criar um arquivo CSS personalizado.

FILE: custom.css
body {
  font-family: sans-serif;
  background-color: white;
  font-size: 12px;
  margin: 20px;
}

h1 {font-size:1.5em;}

table {
  border: solid;
  border-color: black;
  border-width: 2px;
  border-collapse: collapse;
  margin-bottom: 20px;
  text-align: center;
  padding: 0px;
}

.t1 .header {
  color: white;
  background-color: black;
  border-bottom: solid;
  border-color: black;
  border-width: 2px;
  font-weight: bold;
}

.t1 .footer {
  border-top: solid;
  border-color: black;
  border-width: 2px;
}

.t1 .col_first {
  border-right: solid;
  border-color: black;
  border-width: 2px;
  text-align: left;
  font-weight: bold;
  width: 75px;
}

.t1 .col {
  width: 50px;
}

.t1 .col_last {
  width: 50px;
  border-left: solid;
  border-color: black;
  border-width: 2px;
}

Executando ./file_knit.r me dá file.html, que se parece com isto:

Exemplo de saída

Portanto, espero que isso possa ser útil para outras pessoas que desejam um pouco mais de formatação na saída do Markdown!

TARehman
fonte
1
Sim, não. Funcionará com Markdown -> HTML, mas não com Markdown -> PDF, Markdown -> DOCX ... A questão é sobre o uso do Markdown em geral não apenas para o propósito de criar arquivos HTML com ele - pode ter sido seu intenção, mas não está escrito lá.
petermeissner de
Você percebeu que estou respondendo minha própria pergunta? Posso editar a pergunta ou marcá-la de forma diferente se você achar que isso ajudaria?
TARehman de
A propósito, no momento desta resposta, o knitr só oferecia suporte a HTML. É por isso que a pergunta não diz nada explicitamente sobre HTML.
TARehman de
jip, mudar a pergunta ajudaria ... mas por que torná-la mais específica quando é mais útil para todos quando é mais ampla e geral? Quanto a você responder à sua própria pergunta, bem, os outros fornecem tabelas no formato Markdown, você fornece tabelas no formato HTML - não está errado, mas acho as outras respostas simplesmente diretas, elegantes e mais úteis. nem todo mundo tem que gostar da sua resposta, não basta que gostem da sua resposta?
petermeissner
7
Você mesmo disse que minha resposta não está errada, mas que outras são melhores. A aplicação correta do sistema de votação é votar positivamente nas melhores respostas, não votar negativamente nas minhas. Veja também aqui: stackoverflow.com/help/privileges/vote-down "Use seus votos negativos sempre que encontrar uma postagem notoriamente descuidada e sem esforço despendido, ou uma resposta que seja clara e talvez perigosamente incorreta."
TARehman
18

Existem funções no panderpacote:

> library(pander)
> pandoc.table(head(iris)[, 1:3])

-------------------------------------------
 Sepal.Length   Sepal.Width   Petal.Length 
-------------- ------------- --------------
     5.1            3.5           1.4      

     4.9             3            1.4      

     4.7            3.2           1.3      

     4.6            3.1           1.5      

      5             3.6           1.4      

     5.4            3.9           1.7      
-------------------------------------------
Marius
fonte
4
Obrigado por promover pander:) Observe que você também pode usar o método S3 genérico para salvar alguns caracteres para digitar, como:pander(head(iris)[, 1:3])
daroczig
12

Não é muito difícil fazer sua própria função personalizada. Aqui está uma prova de conceito muito simples para gerar uma tabela rmarkdown de data.frame:

   rmarkdownTable <- function(df){
      cat(paste(names(df), collapse = "|"))
      cat("\n")
      cat(paste(rep("-", ncol(df)), collapse = "|"))
      cat("\n")

      for(i in 1:nrow(df)){
        cat(paste(df[i,], collapse = "|"))
        cat("\n")
        }
    invisible(NULL)
    }

No documento .Rmd, você usaria a função com results = 'asis':

```{r, results = 'asis'}
rmarkdownTable <- function(df){
  cat(paste(names(df), collapse = "|"))
  cat("\n")
  cat(paste(rep("-", ncol(df)), collapse = "|"))
  cat("\n")

  for(i in 1:nrow(df)){
    cat(paste(df[i,], collapse = "|"))
    cat("\n")
    }
invisible(NULL)
}

rmarkdownTable(head(iris))
```

O código acima forneceria a seguinte figura (no exemplo, esta é a saída em pdf, mas como a tabela está em markdwon, você também poderia tricotar em html ou word).

insira a descrição da imagem aqui A partir daqui - e lendo o código de outras pessoas - você pode descobrir como manipular o texto para gerar a tabela desejada e criar funções mais personalizadas.

Carlos Cinelli
fonte
1
isso é ótimo, mas você sabe como alinhar no lado esquerdo em vez de centralizado?
Patrick de
3

use uma combinação de knitr :: kable e xtable em seu documento markdown.

library("knitr","xtable")

para um data.frame simples -

kable(head(mtcars[,1:4]),format="markdown")
kable(head(mtcars[,1:4]),format="pandoc",caption="Title of the table")

format="pandoc" permite mais opções como legenda.

Agora, a combinação para o resumo do modelo .

data(tli)
fm1 <- aov(tlimth ~ sex + ethnicty + grade + disadvg, data=tli)
kable(xtable(fm1), caption = "Annova table")

para ainda mais opções, olhe para stargazerpacote em vez de xtable.

exemplo para uso pessoal

Pankil Shah
fonte
1

Para escrever / criar tabelas Markdown em R, você também pode usar MarkdownReports MarkDown_Table_writer_DF_RowColNames() ou MarkDown_Table_writer_NamedVector()funções. Você simplesmente passa um quadro / matriz de dados com nomes de dimensão, ou um vetor com nomes, e ele analisa e escreve a tabela no formato Markdown.

bud.dugong
fonte
0

Minha função para Gitlab:

to_markdown<-function(df) {
    wrap<-function(x,sep=" ") paste0("|", sep, paste(x, collapse=paste0(sep,"|",sep)), sep, "|", sep=sep)
    paste0(wrap(colnames(df)),
    "\n",
    wrap(rep("------", ncol(df)),sep=""),
    "\n",
    paste(apply(df, 1, wrap), collapse="\n"))
}

cat(to_markdown(head(iris[,1:3])))
| Sepal.Length | Sepal.Width | Petal.Length | 
|------|------|------|
| 5.1 | 3.5 | 1.4 | 
| 4.9 | 3 | 1.4 | 
| 4.7 | 3.2 | 1.3 | 
| 4.6 | 3.1 | 1.5 | 
| 5 | 3.6 | 1.4 | 
| 5.4 | 3.9 | 1.7 | 
Valentas
fonte