Programowe tworzenie tabel Markdown w języku R za pomocą KnitR


103

Właśnie zaczynam się uczyć o KnitR i wykorzystaniu Markdown do generowania dokumentów i raportów R. Wygląda na to, że jest to idealne rozwiązanie dla wielu codziennych raportów, które mam do czynienia z moją pracą. Jednak jedną rzeczą, której nie widzę, jest łatwy sposób drukowania ramek i tabel danych przy użyciu formatowania Markdown (coś w rodzaju xtable, ale z Markdown zamiast LaTeX lub HTML). Wiem, że mogę po prostu osadzić wynik HTML z xtable, ale zastanawiałem się, czy istnieją rozwiązania oparte na Markdown?


3
Biorąc pod uwagę xtable i html .. Wydrukuj kod HTML z print(xtable(data), type = "html").
— user974514

7
@TARehman Twoje pytanie przypomniało mi, że nadal nie ma rozwiązania, które generowałoby tabele bezpośrednio kompatybilne z knitr, więc wysłałem prośbę o ściągnięcie, panderaby dodać styl tabeli. W przyszłych wersjach panderpowinno być to możliwepandoc.table(iris, style="rmarkdown")
— Marius

1
@Marius Czy wiesz, dlaczego pandoc nie jest częścią CRAN? Albo kiedy może stać się jego częścią? Po prostu ciekawy.
— TARehman

2
@TARehman Nie jestem do końca pewien, czy miałeś na myśli pandora czy pandoca. panderpowinien być na CRAN. pandoc to program napisany w Haskell, który konwertuje do iz wielu różnych formatów, w żaden sposób nie jest specyficzny dla języka R.
— Marius

1
Przepraszam, chodziło mi o to pander, czego ostatnio nie było w CRAN - nie pandoc. Moja wina. :)
— TARehman

Odpowiedzi:


122

Teraz knitr(od wersji 1.3) pakiet zawiera kablefunkcję tworzenia tabel:

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

AKTUALIZACJA : jeśli otrzymujesz surową przecenę w dokumencie, wypróbuj results = "asis"opcję konfiguracji fragmentu.


24
gdy uruchamiasz wewnątrz knitr, możesz pominąć formatargument, ponieważ knitr zna format wyjściowy i automatycznie go ustawi
— Yihui Xie

3
@Yihui Jesteś niesamowity
— izomorfizm

2
Próbowałem tego, ale `` {r} kable (...) po prostu pokazuje surową przecenę
— Alex Brown

6
Spróbuj ustawić opcję lokalnego fragmentu na results = asis.
— Artem Klevtsov

5
FYI knitr wymaga teraz polecenia w formacieresults = 'asis'
— Stedy

32

Dwa pakiety, które to zrobią, to pander

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

Lub ascii

pander to nieco inne podejście do tworzenia raportów (ale może być przydatne w przypadku tej funkcji).

asciipozwoli Ci printz type = 'pandoc(lub różne inne smaki Przecena)

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

Zauważ, że w obu tych przypadkach jest skierowany do użycia pandocdo konwersji z markdown do pożądanego typu dokumentu, jednak użycie style='rmarkdown'spowoduje utworzenie tabel zgodnych z tym markdownpakietem i wbudowaną konwersją w rstudio.


3
Jeszcze uwaga o pander: może produkować rmarkdownstylizowane stoliki także obok innych np .:pander(head(iris[,1:3]), style = 'rmarkdown')
— daroczig

@daroczig - Dzięki i zanotowałem w odpowiedzi teraz,
— mnel

26

Chciałem tylko zaktualizować to, co postanowiłem zrobić. Używam hwriterteraz pakietu do drukowania tabel i używam row.*icol.* do umieszczania klas CSS w różnych elementach. Następnie napisałem niestandardowy CSS, aby mój wyświetlacz był taki, jak chciałem. Oto przykład na wypadek, gdyby ktoś inny miał do czynienia z czymś podobnym.

Najpierw utwórz plik, który wykona knittingi zmieni Markdown na HTML:

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

library(knitr)
library(markdown)

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

Następnie utwórz rzeczywisty plik Markdown:

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

Na koniec po prostu utwórz niestandardowy plik CSS.

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

Uruchomienie ./file_knit.rdaje mi plik.html, który wygląda następująco:

Przykładowe dane wyjściowe

Miejmy nadzieję, że może to być pomocne dla innych, którzy chcą nieco więcej formatowania w danych wyjściowych Markdown!


1
Tak, nie. Będzie działać z Markdown -> HTML, ale nie z Markdown -> PDF, Markdown -> DOCX ... Pytanie dotyczy używania Markdown w ogóle nie tylko w celu tworzenia z nim plików HTML - mogło to być Twoje zamiar, ale nie jest tam zapisany.
— petermeissner

Zauważyłeś, że odpowiadam na własne pytanie? Mogę edytować pytanie lub otagować je inaczej, jeśli uważasz, że to pomoże?
— TARehman

Nawiasem mówiąc, w momencie tej odpowiedzi knitr obsługiwał tylko HTML. Dlatego pytanie nie mówi wprost o HTML.
— TARehman

jip, zmiana pytania pomogłaby ... ale po co uszczegóławiać je, skoro jest bardziej przydatne dla wszystkich, skoro jest szersze i bardziej ogólne? Jeśli chodzi o to, że odpowiadasz na własne pytanie, inni dostarczają tabele w formacie Markdown, a Ty dostarczasz tabele w formacie HTML - to nie jest złe, ale uważam, że inne odpowiedzi są po prostu rzeczowe, eleganckie i bardziej pomocne. nie każdemu musi podobać się twoja odpowiedź, czy nie wystarczy, że podobała się twoja odpowiedź?
— petermeissner

7
Sam powiedziałeś, że moja odpowiedź nie jest błędna, ale inni są lepsi. Prawidłowe zastosowanie systemu głosowania polega na głosowaniu za lepszymi odpowiedziami, a nie przeciw moim. Zobacz także tutaj: stackoverflow.com/help/privileges/vote-down "Użyj swoich głosów przeciw, gdy napotkasz rażąco niechlujny, niewymagający wysiłku post lub odpowiedź, która jest wyraźnie i być może niebezpiecznie nieprawidłowa."
— TARehman

18

W panderpakiecie znajdują się funkcje :

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

4
Dzięki za promowanie pander:) Pamiętaj, że możesz również użyć ogólnej metody S3, aby zapisać kilka znaków do pander(head(iris)[, 1:3])
— wpisania

12

Stworzenie własnej, dostosowanej funkcji nie jest trudne. Oto bardzo prosty dowód słuszności koncepcji, aby wygenerować tabelę rmarkdown 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)
    }

W dokumencie .Rmd możesz użyć funkcji z 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))
```

Powyższy kod dałby następujący rysunek (w przykładzie jest to plik wyjściowy w formacie PDF, ale ponieważ tabela jest w markdwon, można ją również połączyć w html lub słowo).

wprowadź opis obrazu tutaj Stąd - i czytając kod innych osób - możesz dowiedzieć się, jak manipulować tekstem, aby wygenerować żądaną tabelę i stworzyć bardziej spersonalizowane funkcje.


1
to jest świetne, ale czy wiesz, jak to wyrównać po lewej stronie zamiast wyśrodkować?
— Patrick,

3

użyj kombinacji knitr :: kable i xtable w swoim dokumencie przeceny.

library("knitr","xtable")

dla prostej ramki danych -

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

format="pandoc" udostępnia więcej opcji, takich jak podpis.

Teraz kombinacja do podsumowania modelu .

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

aby uzyskać jeszcze więcej opcji, spójrz na stargazerpakiet zamiast xtable.

przykład do użytku osobistego


1

Aby pisać / tworzyć tabele Markdown w R, możesz również użyć funkcji MarkdownReports MarkDown_Table_writer_DF_RowColNames() lub MarkDown_Table_writer_NamedVector()funkcji. Po prostu przekazujesz ramkę / macierz danych z nazwami wymiarów lub wektor z nazwami, a on analizuje i zapisuje tabelę w formacie Markdown.


0

Moja funkcja dla 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 | 
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.