Programmgesteuertes Erstellen von Markdown-Tabellen in R mit KnitR

103

Ich fange gerade an, etwas über KnitR und die Verwendung von Markdown beim Generieren von R-Dokumenten und Berichten zu lernen. Dies scheint perfekt für einen Großteil der täglichen Berichterstattung zu sein, die ich mit meiner Arbeit zu tun habe. Eine Sache, die ich jedoch nicht sehe, ist eine einfache Möglichkeit, Datenrahmen und Tabellen mithilfe der Markdown-Formatierung zu drucken (ähnlich xtable, jedoch mit Markdown anstelle von LaTeX oder HTML). Ich weiß, dass ich nur die HTML-Ausgabe von xtable einbetten kann, aber ich habe mich gefragt, ob es Markdown-basierte Lösungen gibt.

TARehman
quelle
3
Berücksichtigen Sie xtable und html. Drucken Sie HTML-Code mit print(xtable(data), type = "html").
user974514
7
@TARehman Ihre Frage hat mich daran erinnert, dass es immer noch keine Lösung gibt, mit der Tabellen direkt kompatibel sind. Deshalb knitrhabe ich eine Pull-Anfrage gesendet pander, um den Tabellenstil hinzuzufügen. In zukünftigen Versionen von pandersollten Sie in der Lage seinpandoc.table(iris, style="rmarkdown")
Marius
1
@Marius Weißt du zufällig, warum Pandoc nicht Teil von CRAN ist? Oder wann könnte es ein Teil davon werden? Nur neugierig.
TARehman
2
@ TARehman Ich bin mir nicht ganz sicher, ob du Pander oder Pandoc meinst. pandersollte auf CRAN sein. pandoc ist ein in Haskell geschriebenes Programm, das in und aus einer Vielzahl verschiedener Formate konvertiert. Es ist in keiner Weise spezifisch für R.
Marius
1
Entschuldigung, ich meinte pander, das war nicht auf CRAN , als ich es das letzte Mal gehört hatte - nicht pandoc. Mein Fehler. :)
TARehman

Antworten:

122

Das knitrPaket (seit Version 1.3) enthält jetzt die kableFunktion für Erstellungstabellen:

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

AKTUALISIERT : Wenn in einem Dokument ein roher Abschlag angezeigt wird, versuchen Sie, die results = "asis"Option " Block einrichten" einzurichten .

Artem Klevtsov
quelle
24
Wenn Sie in knitr laufen, können Sie das formatArgument weglassen, da knitr das Ausgabeformat kennt und es automatisch
festlegt
3
@ Yihui Sie sind erstaunlich
Isomorphismen
2
Ich habe es versucht, aber `` `{r} kable (...) zeigt nur den rohen Abschlag
Alex Brown
6
Versuchen Sie, die Option für lokale Chunks auf zu setzen results = asis.
Artem Klevtsov
5
FYI Knitr benötigt jetzt den Befehl im Formatresults = 'asis'
Stedy
32

Zwei Pakete, die dies tun, sind Pander

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

Oder ascii

pander ist ein etwas anderer Ansatz für die Berichtserstellung (kann jedoch für diese Funktion nützlich sein).

asciiermöglicht es Ihnen printmit type = 'pandoc(oder verschiedenen anderen Markdown-Geschmacksrichtungen)

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

Beachten Sie, dass in beiden Fällen pandocdie Konvertierung von Markdown in den gewünschten Dokumenttyp verwendet werden soll. Bei Verwendung von style='rmarkdown'werden jedoch Tabellen erstellt, die mit diesem markdownPaket kompatibel sind , und die integrierte Konvertierung in rstudio.

mnel
quelle
3
Nur ein Hinweis zu pander: Es kann die rmarkdowngestalteten Tische auch neben anderen produzieren, zB:pander(head(iris[,1:3]), style = 'rmarkdown')
Daroczig
@ Daroczig - Danke und in der Antwort jetzt vermerkt,
mnel
26

Ich wollte dies nur mit dem aktualisieren, was ich beschlossen habe. Ich verwende das hwriterPaket gerade, um Tabellen auszudrucken, und verwende die Funktionen row.*und col.*, um CSS-Klassen auf verschiedene Elemente anzuwenden. Dann schrieb ich benutzerdefiniertes CSS, um meine Anzeige so zu gestalten, wie ich es wollte. Hier ist ein Beispiel für den Fall, dass sich jemand anderes mit etwas Ähnlichem befasst.

Erstellen Sie zunächst eine Datei, die knittingdas ausführt, und ändern Sie den Markdown in HTML:

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

library(knitr)
library(markdown)

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

Erstellen Sie als Nächstes die eigentliche Markdown-Datei:

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

Zum Schluss erstellen Sie einfach eine benutzerdefinierte CSS-Datei.

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

Das Ausführen ./file_knit.rgibt mir file.html, die so aussieht:

Beispielausgabe

Hoffentlich kann dies für andere hilfreich sein, die etwas mehr Formatierung in der Markdown-Ausgabe wünschen!

TARehman
quelle
1
Ja, nein. Funktioniert mit Markdown -> HTML, aber nicht mit Markdown -> PDF, Markdown -> DOCX ... Die Frage ist, ob Markdown im Allgemeinen nicht nur zum Erstellen von HTML-Dateien verwendet werden soll Absicht, wird aber dort nicht niedergeschrieben.
Petermeissner
Haben Sie bemerkt, dass ich meine eigene Frage beantworte? Ich kann die Frage bearbeiten oder anders markieren, wenn Sie denken, dass es helfen würde?
TARehman
Zum Zeitpunkt dieser Antwort unterstützte knitr übrigens nur HTML. Deshalb sagt die Frage nichts explizit über HTML aus.
TARehman
jip, die Frage zu ändern würde helfen ... aber warum sollte man sie spezifischer machen, wenn sie für alle von Nutzen ist, wenn sie breiter und allgemeiner ist? In Bezug auf die Beantwortung Ihrer eigenen Frage stellen die anderen Tabellen im Markdown-Format zur Verfügung. Sie stellen Tabellen im HTML-Format zur Verfügung - es ist nicht falsch, aber ich finde die anderen Antworten einfach auf den Punkt gebracht, elegant und hilfreicher. nicht jeder muss deine Antwort mögen, reicht es nicht aus, dass dir deine Antwort gefallen hat?
Petermeissner
7
Sie selbst haben gesagt, dass meine Antwort nicht falsch ist, sondern dass andere besser sind. Die richtige Anwendung des Abstimmungssystems besteht darin, die besseren Antworten zu verbessern und meine nicht zu bewerten. Siehe auch hier: stackoverflow.com/help/privileges/vote-down "Verwenden Sie Ihre Downvotes immer dann, wenn Sie auf einen ungeheuer schlampigen, mühelosen Beitrag oder eine Antwort stoßen, die eindeutig und möglicherweise gefährlich falsch ist."
TARehman
18

Das panderPaket enthält Funktionen :

> 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
quelle
4
Vielen Dank für die Werbung pander:) Bitte beachten Sie, dass Sie auch die generische S3-Methode verwenden können, um ein paar Zeichen für die pander(head(iris)[, 1:3])
Eingabe
12

Es ist nicht sehr schwer, eine eigene Funktion zu erstellen. Hier ist ein sehr einfacher Proof of Concept zum Generieren einer Rmarkdown-Tabelle von a 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)
    }

In einem RMD-Dokument würden Sie dann die Funktion verwenden mit 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))
```

Der obige Code würde Ihnen die folgende Abbildung geben (im Beispiel ist dies die PDF-Ausgabe, aber da sich die Tabelle in markdwon befindet, können Sie auch in HTML oder Word stricken).

Geben Sie hier die Bildbeschreibung ein Von hier aus - und beim Lesen des Codes anderer Personen - können Sie herausfinden, wie Sie den Text bearbeiten, um die gewünschte Tabelle zu generieren und individuellere Funktionen zu erstellen.

Carlos Cinelli
quelle
1
Das ist großartig, aber wissen Sie, wie Sie dies auf der linken Seite anstatt zentriert ausrichten können?
Patrick
3

Verwenden Sie eine Kombination aus knitr :: kable und xtable in Ihrem Markdown-Dokument.

library("knitr","xtable")

für einen einfachen data.frame -

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

format="pandoc" ermöglicht mehr Optionen wie Beschriftung.

Nun die Kombination zur Modellzusammenfassung .

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

Für noch mehr Optionen schauen Sie sich das stargazerPaket anstelle von an xtable.

Beispiel für den persönlichen Gebrauch

Pankil Shah
quelle
1

Zum Schreiben / Erstellen von Markdown-Tabellen in R können Sie auch MarkdownReports ' MarkDown_Table_writer_DF_RowColNames() oder verwendenMarkDown_Table_writer_NamedVector() Funktionen verwenden. Sie übergeben einfach einen Datenrahmen / eine Matrix mit Dimensionsnamen oder einen Vektor mit Namen und analysieren und schreiben die Tabelle im Markdown-Format.

bud.dugong
quelle
0

Meine Funktion für 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
quelle