Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print python pandas data frame using kable() #2071

Closed
youngwoos opened this issue Nov 10, 2021 · 8 comments
Closed

Print python pandas data frame using kable() #2071

youngwoos opened this issue Nov 10, 2021 · 8 comments

Comments

@youngwoos
Copy link

I use R and python in rmarkdown to make word document.

Is there any way to make pandas data frame to kable?

What i found is that (1)import pandas data frame object to R Chunk and (2) use kable(). This work well but i don't want this step every time printing data frame.

Is there any other convenient way or some python chunk option?

@youngwoos youngwoos changed the title Print pandas data frame using kable() Print python pandas data frame using kable() Nov 10, 2021
@cderv
Copy link
Collaborator

cderv commented Nov 12, 2021

kable() is from R. So I guess somehow R needs to be called.

reticulate allows you to easily call python object from R and R from python, especially inside an Rmd document between R and Python chunk. Is this what you are doing already ?

https://rstudio.github.io/reticulate/articles/r_markdown.html#calling-python-from-r-1

You could print python data frame using kable() by calling it this way

---
title: "test"
output: 
  html_document: default
---

```{r}
library(reticulate)
```


```{python}
import pandas as pd
df1 = pd.DataFrame(
    {
        "A": ["A0", "A1", "A2", "A3"],
        "B": ["B0", "B1", "B2", "B3"],
        "C": ["C0", "C1", "C2", "C3"],
        "D": ["D0", "D1", "D2", "D3"],
    },
    index=[0, 1, 2, 3],
)
```

`r knitr::kable(py$df1)`

As you see, it is only one line to print using kable(), so same if you were calling the function on a R data.frame directly.

Is this what you are doing already ?

@youngwoos
Copy link
Author

kable() is from R. So I guess somehow R needs to be called.

reticulate allows you to easily call python object from R and R from python, especially inside an Rmd document between R and Python chunk. Is this what you are doing already ?

https://rstudio.github.io/reticulate/articles/r_markdown.html#calling-python-from-r-1

You could print python data frame using kable() by calling it this way

---
title: "test"
output: 
  html_document: default
---

```{r}
library(reticulate)
import pandas as pd
df1 = pd.DataFrame(
    {
        "A": ["A0", "A1", "A2", "A3"],
        "B": ["B0", "B1", "B2", "B3"],
        "C": ["C0", "C1", "C2", "C3"],
        "D": ["D0", "D1", "D2", "D3"],
    },
    index=[0, 1, 2, 3],
)

r knitr::kable(py$df1)


As you see, it is only one line to print using `kable()`, so same if you were calling the function on a R data.frame directly.

Is this what you are doing already ?

Thank you for your answer.

Yes, this is what I’am doing but i am looking for other way to not to calling python object to R chunk. Because I am writing long document using python code so calling python object to R chunk every time when printing is very inconvenient.

@cderv
Copy link
Collaborator

cderv commented Nov 16, 2021

What do you look for exactly ? How would you ideal use case be like ?

You would prefer to write the table output from Python directly ? pandas has a to_markdown() method that could ouyptut something similar to kable()

---
title: "test"
output: 
  html_document: default
---

```{r}
library(reticulate)
```


```{python, results = "asis"}
import pandas as pd
df1 = pd.DataFrame(
    {
        "A": ["A0", "A1", "A2", "A3"],
        "B": ["B0", "B1", "B2", "B3"],
        "C": ["C0", "C1", "C2", "C3"],
        "D": ["D0", "D1", "D2", "D3"],
    },
    index=[0, 1, 2, 3],
)
print(df1.to_markdown(index = False))
```

image

Maybe there are other Python modules that exists to output some table in Markdown format that would be compatible with Pandoc.

Otherwise, passing through R would be needed anyway.
Maybe that is not the issue to pass by R but that you would like a way to the Pandas data frame to be output as a markdown table without you calling a function each time ?

I am just trying to understand better what you are thinking about how this should work. You did not give us some example of how it could look like so it is hard for me to know for sure what you are thinking off.

Possibly, this would be a feature request for reticulate engine but not sure.

Thank you

@youngwoos
Copy link
Author

Thank you for your kindness.

I'm writing book using python code. I use rmarkdown and knit to word document file(.docx).
I think many book readers will use jupyter notebook. So i want to print data frame looks like printed on jupyter notebook.

When i use R code this is easy. Just add df_print: kable to yaml header. I don't need to do any extra job.

---
title: "R data frame"
output:
  word_document:
    df_print: kable
---
```{r}
df1 <- data.frame(
  A = c("A0", "A1", "A2", "A3"),
  B = c("B0", "B1", "B2", "B3"),
  C = c("C0", "C1", "C2", "C3"),
  D = c("D0", "D1", "D2", "D3")
)

df1

image

But using Python code, df_print: kable is not working. I have to call python object to R chunk and use kable() every time.
And to make this extra job invisible, i have to make more chunk every time using eval and echo.

---
title: "Python data frame"
output:
  word_document:
    df_print: kable
---

```{python}
import pandas as pd
df1 = pd.DataFrame(
    {
        "A": ["A0", "A1", "A2", "A3"],
        "B": ["B0", "B1", "B2", "B3"],
        "C": ["C0", "C1", "C2", "C3"],
        "D": ["D0", "D1", "D2", "D3"],
    },
    index=[0, 1, 2, 3],
)
```

```{python eval = F}
df1
```

```{r echo = F}
library(reticulate)
library(knitr)
kable(py$df1)
```

image

So, I want to print pandas data frame looking good like jupyter notebook without calling python object to R chunk.

I know this is some weird because i can just use jupyter notebook. But writing document on rmarkdown is much better than jupyter notebook.

If this is not issue about knitr, please let me know where to ask.
Thank you

@cderv
Copy link
Collaborator

cderv commented Nov 17, 2021

But using Python code, df_print: kable is not working.

df_print will only have impact when method knit_print.data.frame is called.

I don't know how reticulate handle the result of a Python data.frame currently. I think this is not supported and maybe this issue and comment is related to what you seek rstudio/reticulate#783 (comment)

And to make this extra job invisible, i have to make more chunk every time using eval and echo.

If you do that often, you could leverage the fact that you can create markdown contact programmatically and write a helper for that. Some recipes are in the Cookbook (https://bookdown.org/yihui/rmarkdown-cookbook)

here is an example
---
title: "Python data frame"
output:
  word_document:
    df_print: kable
---

```{r, include=FALSE}
print_df_py <- function(df_name) {
  content <- c(
    "```{python, eval = F}",
    df_name,
    "```",
    "```{r, echo = F}",
    sprintf("py$%s", df_name),
    "```"
  )
  res <- knitr::knit_child(text = content)
  knitr::asis_output(res)
}
```

```{r, include = FALSE}
library(reticulate)
```

```{python}
import pandas as pd
df1 = pd.DataFrame(
    {
        "A": ["A0", "A1", "A2", "A3"],
        "B": ["B0", "B1", "B2", "B3"],
        "C": ["C0", "C1", "C2", "C3"],
        "D": ["D0", "D1", "D2", "D3"],
    },
    index=[0, 1, 2, 3],
)
```

`r print_df_py("df1")`

You could also leverage RStudio snippet feature to have a quick way of inserting the same pieces of markdown several time
https://rstudio.github.io/rstudio-extensions/rstudio_snippets.html

These are just tricks as workaround. To have a similar solution as df_print with R, this would require reticulate support and maybe some adjustment in rmarkdown and / or knitr

@youngwoos
Copy link
Author

the issue(rstudio/reticulate#783 (comment)) is exactly what i thought. thanks to let me know. I will subscribe this issue.

also thank you to tell me alternative way to make function or use snippet. I will try.

thank you!

@cderv
Copy link
Collaborator

cderv commented Nov 30, 2021

Thanks !

I'll close this issue as we can follow the one in reticulate. If something needs to be done, it will be there.

Thanks for reaching out with this!

@cderv cderv closed this as completed Nov 30, 2021
@github-actions
Copy link

github-actions bot commented Jun 1, 2022

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue by following the issue guide (https://yihui.org/issue/), and link to this old issue if necessary.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants