Création de tableaux Markdown par programmation dans R avec KnitR

103

Je commence tout juste à en apprendre davantage sur KnitR et l'utilisation de Markdown dans la génération de documents et de rapports R. Cela semble parfait pour une grande partie des rapports quotidiens que j'ai à faire avec mon travail. Cependant, une chose que je ne vois pas est un moyen facile d'imprimer des cadres de données et des tableaux en utilisant le formatage Markdown (un peu comme xtable, mais avec Markdown au lieu de LaTeX ou HTML). Je sais que je peux simplement intégrer la sortie HTML de xtable, mais je me demandais s'il y avait des solutions basées sur Markdown?

TARehman
la source
3
Considérant xtable et html .. Imprimez le code html avec print(xtable(data), type = "html").
user974514
7
@TARehman Votre question m'a rappelé qu'il n'y avait toujours pas de solution qui produisait des tables directement compatibles avec knitr, donc j'ai envoyé une pull request à panderpour ajouter le style de table. Dans les futures versions de pander, vous devriez pouvoir le fairepandoc.table(iris, style="rmarkdown")
Marius
1
@Marius Savez-vous pourquoi pandoc ne fait pas partie de CRAN? Ou quand cela pourrait en faire partie? Juste curieux.
TARehman
2
@TARehman Je ne sais pas si vous vouliez dire pander ou pandoc. panderdevrait être sur CRAN. pandoc est un programme écrit en Haskell qui convertit vers et à partir d'une grande variété de formats différents, il n'est en aucun cas spécifique à R.
Marius
1
Désolé, je voulais dire pander, ce qui n'était pas sur CRAN la dernière fois que j'avais entendu - non pandoc. Ma faute. :)
TARehman

Réponses:

122

Maintenant knitr(depuis la version 1.3) le package inclut la kablefonction de création de tables:

> 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|

MISE À JOUR : si vous obtenez une réduction brute dans un document, essayez l' results = "asis"option de configuration du bloc.

Artem Klevtsov
la source
24
lors de l'exécution à l'intérieur de knitr, vous pouvez omettre l' formatargument, car knitr est conscient du format de sortie et le définira automatiquement
Yihui Xie
3
@Yihui You are amazing
isomorphismes
2
J'ai essayé ceci, mais `` {r} kable (...) montre juste la démarque brute
Alex Brown
6
Essayez de définir l'option de bloc local sur results = asis.
Artem Klevtsov
5
FYI knitr nécessite maintenant la commande au formatresults = 'asis'
Stedy
32

Deux paquets qui feront cela sont pander

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

Ou ascii

pander est une approche légèrement différente de la construction de rapports (mais peut être utile pour cette fonctionnalité).

asciivous permettra printavec type = 'pandoc(ou diverses autres saveurs de démarque)

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              
--- ------------------ ----------------- ------------------

Notez que dans ces deux cas, il est orienté vers l'utilisation pandocde la conversion du démarque vers le type de document souhaité, mais l'utilisation style='rmarkdown'créera des tables compatibles avec ce markdownpackage et une conversion intégrée dans rstudio.

mnel
la source
3
Juste une note à propos de pander: il peut produire les rmarkdowntables stylisées également à côté d'autres, par exemple:pander(head(iris[,1:3]), style = 'rmarkdown')
daroczig
@daroczig - Merci et noté dans la réponse maintenant,
mnel
26

Je voulais juste mettre à jour cela avec ce que j'avais décidé de faire. J'utilise le hwriterpackage en ce moment pour imprimer des tableaux et j'utilise les fonctionnalités row.*et col.*pour mettre des classes CSS sur différents éléments. Ensuite, j'ai écrit du CSS personnalisé pour faire mon affichage comme je le voulais. Alors, voici un exemple au cas où quelqu'un d'autre aurait affaire à quelque chose de similaire.

Tout d'abord, créez un fichier qui fera le knittinget changer le Markdown en HTML:

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

library(knitr)
library(markdown)

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

Ensuite, créez le fichier Markdown réel:

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"))))
```

Enfin, créez simplement un fichier CSS personnalisé.

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;
}

L'exécution ./file_knit.rme donne file.html, qui ressemble à ceci:

Exemple de sortie

Donc, j'espère que cela pourrait être utile à d'autres qui veulent un peu plus de formatage dans la sortie Markdown!

TARehman
la source
1
Oui, non. Fonctionnera avec Markdown -> HTML mais pas avec Markdown -> PDF, Markdown -> DOCX ... La question est d'utiliser Markdown en général non seulement dans le but de créer des fichiers HTML avec lui - pourrait avoir été votre l'intention, mais n'est pas écrit là-bas.
petermeissner
Avez-vous remarqué que je répondais à ma propre question? Je peux modifier la question ou la taguer différemment si vous pensez que cela pourrait aider?
TARehman
D'ailleurs, au moment de cette réponse, knitr ne supportait que HTML. C'est pourquoi la question ne dit rien explicitement sur HTML.
TARehman
jip, changer la question aiderait ... mais pourquoi la rendre plus spécifique quand elle est plus utile pour tous quand elle est plus large et plus générale? En ce qui concerne votre réponse à votre propre question, les autres fournissent des tableaux au format Markdown, vous fournissez des tableaux au format HTML - ce n'est pas faux, mais je trouve les autres réponses simplement directes, élégantes et plus utiles. tout le monde n'est pas obligé d'aimer votre réponse, ne suffit-il pas d'avoir aimé votre réponse?
petermeissner
7
Vous avez vous-même dit que ma réponse n'est pas fausse, mais que les autres sont meilleurs. L'application correcte du système de vote est de voter pour les meilleures réponses, et non de voter contre les miennes. Voir aussi ici: stackoverflow.com/help/privileges/vote-down "Utilisez vos votes négatifs chaque fois que vous rencontrez un message extrêmement bâclé, sans effort, ou une réponse qui est clairement et peut-être dangereusement incorrecte."
TARehman le
18

Il y a des fonctions dans le panderpackage:

> 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
la source
4
Merci pour la promotion pander:) Veuillez noter que vous pouvez également utiliser la méthode S3 générique pour enregistrer quelques caractères à taper, comme:pander(head(iris)[, 1:3])
daroczig
12

Il n'est pas très difficile de créer votre propre fonction personnalisée. Voici une preuve de concept très simple pour générer une table rmarkdown d'un 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)
    }

Dans le document .Rmd, vous utiliseriez alors la fonction avec 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))
```

Le code ci-dessus vous donnerait la figure suivante (dans l'exemple, il s'agit de la sortie pdf, mais comme le tableau est en markdwon, vous pouvez également le tricoter en html ou en word).

entrez la description de l'image ici De là - et en lisant le code d'autres personnes - vous pouvez comprendre comment manipuler le texte pour générer le tableau que vous voulez et créer des fonctions plus personnalisées.

Carlos Cinelli
la source
1
c'est génial, mais savez-vous comment l'aligner sur le côté gauche au lieu d'être centré?
Patrick
3

utilisez une combinaison de knitr :: kable et xtable dans votre document de démarquage.

library("knitr","xtable")

pour un simple data.frame -

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

format="pandoc" permet plus d'options comme la légende.

Maintenant, la combinaison pour le résumé du modèle .

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

pour encore plus d'options, regardez stargazerpackage au lieu de xtable.

exemple pour usage personnel

Pankil Shah
la source
1

Pour écrire / créer des tables Markdown dans R, vous pouvez également utiliser MarkdownReports ' MarkDown_Table_writer_DF_RowColNames() ou des MarkDown_Table_writer_NamedVector()fonctions. Vous passez simplement un bloc de données / une matrice avec des noms de dimension, ou un vecteur avec des noms, et il analyse et écrit la table au format Markdown.

bud.dugong
la source
0

Ma fonction pour 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
la source