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?

TARehman
źródło
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.

Artem Klevtsov
źródło
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.

mnel
źródło
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!

TARehman
źródło
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      
-------------------------------------------
Marius
źródło
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.

Carlos Cinelli
źródło
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

Pankil Shah
źródło
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.

bud.dugong
źródło
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 | 
Valentas
źródło