Display kable table in line with text -- Sweave Rnw file - dataframe

I have an Rnw file with a table using the kable command. I want the table to be displayed in line with the text that it follows. How can I stop the table from being displayed at the top of the page? This is the Rnw code:
\documentclass{article}
\begin{document}
Here is my data, which is supposed to be below this sentence.
\\
\begin{abstract}
<<>>=
a <- 1; b <-2; c <-3; d <- 4
df.mse <- data.frame(row.names = c("Normal model", "Laplace model"))
df.mse["Normal model", "Normal MLE"] <- a
df.mse["Normal model", "Laplace MLE"] <- b
df.mse["Laplace model", "Normal MLE"] <- c
df.mse["Laplace model", "Laplace MLE"] <-d
library(knitr)
kable(df.mse, caption="approximate MSE for each model/estimator combination")
#
\end{abstract}
\end{document}
I'd prefer for the solution to not involve changing the actual Tex file, as I'd like to carry on working on the Sweave file without worrying about overriding the solution. I know you can use the float package in LaTeX but I'm not sure how to do that in the context of a Sweave file.

Don't include a caption in the call to kable. Then it will just output a tabular environment without wrapping it in a table float. If the caption is not required, that simply means leaving out the caption argument in your call to kable.
If you do want a caption, but want the table placed inline, you need to start your table with \begin{table}[h]. You can put that in the Rnw file like this:
<<>>=
a <- 1; b <-2; c <-3; d <- 4
df.mse <- data.frame(row.names = c("Normal model", "Laplace model"))
df.mse["Normal model", "Normal MLE"] <- a
df.mse["Normal model", "Laplace MLE"] <- b
df.mse["Laplace model", "Normal MLE"] <- c
df.mse["Laplace model", "Laplace MLE"] <-d
library(knitr)
#
\begin{table}[h]
\caption{This is the caption.}
<<echo=FALSE>>=
kable(df.mse)
#
\end{table}

Related

How to modify ggboxplot (ggpubr) to suppress whiskers, but retain access to other boxplot customisations?

Originally I asked this question about suppressing the whiskers on a boxplot made by ggboxplot. (The expected way of setting a geom_boxplot option was not available.) A nice solution appeared which suited the original question. However, the broader question to address is how to suppress whiskers on the boxplot but still retain access to the nice additions in ggpubr, such as being able to automatically compute statistical test results and place these on a boxplot.
I tinkered with the solution from #Julian_Hn to get something like what I want.
There are two issues that someone more knowledgeable might be able to help with, now that I've asked the broader question:
Are there ways to make the solution more efficient?
How can I add in the ability to change the range of x-values? (I tried various methods using ggpar and coord_cartesian, with no effect. I might be lacking knowledge of how to use commands like ggplot_build effectively.)
Here's an example where I suppress whiskers and use stat_kruskal_test to label the boxplot:
ggboxplot_whisker_opt <- function(...)
{
opts <- list(...) # Modification of original question solution to include the original labelled ggboxplot with whiskers and stat info added
# Check if user specified a whiskers arg and set options accordingly
if("whisker" %in% names(opts))
{
whisk <- opts$whisker
opts$whisker <- NULL
} else {
whisk <- TRUE
}
# Additional arguments that might need generalising so that other statistical tests can be used in other applications
if ("kruskal" %in% names(opts))
{ kruskal<-opts$kruskal
opts$kruskal <- NULL
opt.group <- opts$kruskal.options[[1]]
opt.label<- opts$kruskal.options[[2]]
opt.y <- opts$kruskal.options[[3]]
opt.x <- opts$kruskal.options[[4]]
opts$kruskal.options <- NULL
}
pl <- do.call(ggboxplot,opts) # create plot by calling ggboxplot with all user options
if (kruskal){ pl <- pl + stat_kruskal_test(group.by=opt.group,label=opt.label, label.y.npc=opt.y,label.x.npc=opt.x) }
if(!whisk)
{ pl_list <- ggplot_build(pl) # get listed version of ggboxplot object to modify
pl_list$data[[1]]$ymin <- NA # remove the ymin/max that specify the whiskers
pl_list$data[[1]]$ymax <- NA
pl <- ggplot_gtable(pl_list) # convert back to ggplot object
}
# return
pl
}
Here's the application:
set.seed(123)
x <-rnorm(100)
labels <- round(runif(100,1,2))
df <- data.frame(labels=labels, value=x)
# Define the options for the stat_kruskal_test label
KO <- list("group"="labels","label"="as_detailed_italic", "label.y.npc"=0.5,"label.x.npc"=0.5,ylim=c(-1.2, 1.2))
# call the function
output.plot <- ggboxplot_whisker_opt(df, "labels","value", col="labels", legend="none", whisker=FALSE,add=c("mean"), orientation="horizontal" kruskal=TRUE,kruskal.options=KO)
# Plot the result
plot(output.plot)
the issue with modifying was that the returned object was not a ggplot object anymore (wrong comment on my side) but a plot object. I have thought about it and instead of modifying the ggbuilt object, it's also possible to directly pass the coef=0 through to the geom_boxplot layer inside the object returned by ggboxplot:
ggboxplot_whisker_opt <- function(...)
{
opts <- list(...)
# check if user specified a whiskers argument and set options accordingly
if("whisker" %in% names(opts))
{
whisk <- opts$whisker
opts$whisker <- NULL
} else {
whisk <- TRUE
}
pl <- do.call(ggpubr::ggboxplot, opts) # create plot by calling ggboxplot with all user options
if(!whisk)
{
pl$layers[[1]]$stat_params$coef <- 0 # modify coef param of geom_boxplot layer
}
# plot the ggplot and return so other ggplot parts can be added via `+`
pl
}
This function now returns an object compatible with ggpar or adding other ggplot modifiers via +
library(ggplot2)
library(ggpubr)
set.seed(123)
x <- rnorm(100)
labels <- round(runif(100,1,2))
df <- data.frame(labels=labels,
value=x)
testplot <- ggboxplot_whisker_opt(df,"labels","value",whisker=FALSE)
ggpar(testplot,xlim=c(0.5,1.5),
ylim=c(-0.5,0.5))
testplot +
geom_line(data=data.frame(x=c(1,2),y=c(0,0)),aes(x=x,y=y),color="red",lwd=2)

! Package pdftex.def Error - when knitting to PDF

I am able to knit to PDF for the example below:
---
title: "R Notebook"
output:
pdf_document: default
html_notebook: default
html_document:
df_print: paged
---
Table 1 example:
```{r, warning=FALSE, message=FALSE, echo=FALSE, include=FALSE, fig.pos="H"}
library(magrittr)
library(tidyverse)
library(kableExtra)
library(readxl)
library(modelsummary)
library(scales)
tmp <- mtcars
# create a list with individual variables
# remove missing and rescale
tmp_list <- lapply(tmp, na.omit)
tmp_list <- lapply(tmp_list, scale)
# create a table with `datasummary`
# add a histogram with column_spec and spec_hist
# add a boxplot with colun_spec and spec_box
emptycol = function(x) " "
final_4_table <- datasummary(mpg + cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb ~ N + Mean + SD + Heading("Boxplot") * emptycol + Heading("Histogram") * emptycol, data = tmp) %>%
column_spec(column = 5, image = spec_boxplot(tmp_list)) %>%
column_spec(column = 6, image = spec_hist(tmp_list))
```
```{r finaltable, echo=FALSE}
final_4_table
```
However, I cannot knit to PDF my own code which involves more variables. My R Markdown starts by reading my excel file and then it is pretty much the same as example above:
---
title: "table1"
output:
pdf_document: default
html_document:
df_print: paged
---
Table 1
```{r prep-tableone, message=FALSE, warning=FALSE, echo=FALSE, include=FALSE, fig.pos="H"}
library(magrittr)
library(tidyverse)
library(kableExtra)
library(readxl)
library(modelsummary)
library(scales)
### set directory
setwd("/etcetc1")
## read dataset
my_dataset <- read_excel("my_dataset.xlsx")
my_dataset <- as.data.frame(my_dataset)
...
I can run this code in R script; it works just fine. I can also knit this code to HTML just fine. When trying to knit to PDF I get the following error:
output file: table1test.knit.md
! Package pdftex.def Error: File `table1test_files/figure-latex//boxplot_65c214bae9bb.pdf' not found: using draft setting.
Error: LaTeX failed to compile table1test.tex. See https://yihui.org/tinytex/r/#debugging for debugging tips. See table1test.log for more info.
In addition: Warning messages:
1: package 'ggplot2' was built under R version 4.1.1
2: package 'tibble' was built under R version 4.1.1
3: package 'tidyr' was built under R version 4.1.1
4: In in_dir(input_dir(), evaluate(code, envir = env, new_device = FALSE, :
You changed the working directory to /etcetc1 (probably via setwd()). It will be restored to /etcetc2. See the Note section in ?knitr::knit
Execution halted
Am I missing any packages? Do you know what might be happening?
I use TeXShop for LaTeX.

kable unable to output unicode character in pdf_book (bookdown)

I am trying to use the checkmark unicode character (\u2713) in a table rendered by kable in a bookdown project. A MWE consists in the following 2 files (index.Rmd, preamble.tex) part of the generated minimal bookdown project.
index.Rmd
---
title: "A Minimal Book Example"
subtitle: "subtitle"
lang: fr
author: "Yihui Xie"
date: "`r Sys.Date()`"
site: bookdown::bookdown_site
documentclass: book
mainfont: Arial
mathfont: Arial
bibliography: [book.bib, packages.bib]
biblio-style: apalike
link-citations: yes
subparagraph: yes
description: "This is a minimal example of using the bookdown package to write a book. The output format for this example is bookdown::gitbook."
---
```{r setup, include=FALSE}
# Set locale to french for month and day names (calendar plots)
Sys.setlocale(locale = 'French')
# Load all needed libraries
if(!require('pacman'))install.packages('pacman')
pacman::p_load(kableExtra)
```
(ref:O3) O~3~
# Prerequisites
✓
```{r stations-polluants, echo=FALSE}
stations_polluants_table <- data.frame(
stations = c("41B001", "41B004", "41B011", "41MEU1", "41N043", "41R001", "41R002", "41R012", "41WOL1", "Total / polluant"),
O3 = c("", rep("✓", 5), "", rep("\u2713", 2), "7")
)
kable(stations_polluants_table, col.names = c("Station", "(ref:O3)"), booktabs = T, align = "c", caption = "Caption text") %>%
row_spec(0, bold = T) %>%
row_spec(10, bold = T) %>%
collapse_rows(columns = 1, latex_hline = "major", valign = "top")
```
```{r include=FALSE}
# automatically create a bib database for R packages
knitr::write_bib(c(
.packages(), 'bookdown', 'knitr', 'rmarkdown'
), 'packages.bib')
```
preamble.tex
\usepackage{booktabs}
\newfontfamily{\unicodefont}{Arial Unicode MS}
\usepackage{newunicodechar}
\newunicodechar{✓}{{\unicodefont{✓}}}
By compiling in PDF with rmarkdown::render_site(output_format = 'bookdown::pdf_book', encoding = 'UTF-8') one can notice that ✓ is correctly rendered in the text, while it is replaced by <U+2713> in the generated table. I also tried to use \u2713 in the table without more success.
What am I doing wrong ? Please note that, even if the prefered output is PDF, I would also like to compile as gitbook (so Rmd files need to stay independent from the output format).
Many thanks.
After having a moment of clarity, the solution simply lies in using text references in bookdown, i.e. (ref:check) ✓ and use the reference within the table.
index.Rmd
```{r setup, include=FALSE}
# Set locale to french for month and day names (calendar plots)
Sys.setlocale(locale = 'French')
# Load all needed libraries
if(!require('pacman'))install.packages('pacman')
pacman::p_load(kableExtra)
```
(ref:O3) O~3~
# Prerequisites
✓
(ref:check) ✓
```{r stations-polluants, echo=FALSE}
stations_polluants_table <- data.frame(
stations = c("41B001", "41B004", "41B011", "41MEU1", "41N043", "41R001", "41R002", "41R012", "41WOL1", "Total / polluant"),
O3 = c("", rep("(ref:check)", 5), "", rep("(ref:check)", 2), "7")
)
kable(stations_polluants_table, col.names = c("Station", "(ref:O3)"), booktabs = T, align = "c", caption = "Caption text") %>%
row_spec(0, bold = T) %>%
row_spec(10, bold = T) %>%
collapse_rows(columns = 1, latex_hline = "major", valign = "top")
```
```{r include=FALSE}
# automatically create a bib database for R packages
knitr::write_bib(c(
.packages(), 'bookdown', 'knitr', 'rmarkdown'
), 'packages.bib')
```

Issue when trying to plot geom_tile using ggplotly

I would like to plot a ggplot2 image using ggplotly
What I am trying to do is to initially plot rectangles of grey fill without any aesthetic mapping, and then in a second step to plot tiles and change colors based on aesthetics. My code is working when I use ggplot but crashes when I try to use ggplotly to transform my graph into interactive
Here is a sample code
library(ggplot2)
library(data.table)
library(plotly)
library(dplyr)
x = rep(c("1", "2", "3"), 3)
y = rep(c("K", "B","A"), each=3)
z = sample(c(NA,"A","L"), 9,replace = TRUE)
df <- data.table(x,y,z)
p<-ggplot(df)+
geom_tile(aes(x=x,y=y),width=0.9,height=0.9,fill="grey")
p<-p+geom_tile(data=filter(df,z=="A"),aes(x=x,y=y,fill=z),width=0.9,height=0.9)
p
But when I type this
ggplotly(p)
I get the following error
Error in [.data.frame(g, , c("fill_plotlyDomain", "fill")) :
undefined columns selected
The versions I use are
> packageVersion("plotly")
1 ‘4.7.1
packageVersion("ggplot2")
1 ‘2.2.1.9000’
##########Edited example for Arthur
p<-ggplot(df)+
geom_tile(aes(x=x,y=y,fill="G"),width=0.9,height=0.9)
p<- p+geom_tile(data=filter(df,z=="A"),aes(x=x,y=y,fill=z),width=0.9,height=0.9)
p<-p+ scale_fill_manual(
guide = guide_legend(title = "test",
override.aes = list(
fill =c("red","white") )
),
values = c("red","grey"),
labels=c("A",""))
p
This works
but ggplotly(p) adds the grey bar labeled G in the legend
The output of the ggplotly function is a list with the plotly class. It gets printed as Plotly graph but you can still work with it as a list. Moreover, the documentation indicates that modifying the list makes it possible to clear all or part of the legend. One only has to understand how the data is structured.
p<-ggplot(df)+
geom_tile(aes(x=x,y=y,fill=z),width=0.9,height=0.9)+
scale_fill_manual(values = c(L='grey', A='red'), na.value='grey')
p2 <- ggplotly(p)
str(p2)
The global legend is here in p2$x$layout$showlegend and setting this to false displays no legend at all.
The group-specific legend appears at each of the 9 p2$x$data elements each time in an other showlegend attribute. Only 3 of them are set to TRUE, corresponding to the 3 keys in the legend. The following loop thus clears all the undesired labels:
for(i in seq_along(p2$x$data)){
if(p2$x$data[[i]]$legendgroup!='A'){
p2$x$data[[i]]$showlegend <- FALSE
}
}
Voilà!
This works here:
ggplot(df)+
geom_tile(aes(x=x,y=y,fill=z),width=0.9,height=0.9)+
scale_fill_manual(values = c(L='grey', A='red'), na.value='grey')
ggplotly(p)
I guess your problem comes from the use of 2 different data sources, df and filter(df,z=="A"), with columns with the same name.
[Note this is not an Answer Yet]
(Putting for reference, as it is beyond the limits for comments.)
The problem is rather complicated.
I just finished debugging the code of plotly. It seems like it's occurring here.
I have opened an issue in GitHub
Here is the minimal code for the reproduction of the problem.
library(ggplot2)
set.seed(1503)
df <- data.frame(x = rep(1:3, 3),
y = rep(1:3, 3),
z = sample(c("A","B"), 9,replace = TRUE),
stringsAsFactors = F)
p1 <- ggplot(df)+
geom_tile(aes(x=x,y=y, fill="grey"), color = "black")
p2 <- ggplot(df)+
geom_tile(aes(x=x,y=y),fill="grey", color = "black")
class(plotly::ggplotly(p1))
#> [1] "plotly" "htmlwidget"
class(plotly::ggplotly(p2))
#> Error in `[.data.frame`(g, , c("fill_plotlyDomain", "fill")): undefined columns selected

Create pdf-format table that can wrap the text well in rmarkdown

I used the rmarkdown to create a pdf file, where some tables are included in the output. The tables are created by using pander function.
As you see, the output does not wrap the text well, so the output is quite dirty.
Suppose the code is as follows:
title: "Untitled"
output: pdf_document
---
```{r kable}
library(xtable)
a <- rep(1,5)
b <- rep("33333333333333333333333333333333333333333333333333333333333333333", 5)
c <- rep("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", 5)
data <- as.data.frame( cbind(a, b, c) )
```
```{r b}
library(pander)
pander(data, split.cells = 5, split.table = Inf)
```
```{r c}
pander(data, split.cells = 5)
```
I do not know if there is any method to create pdf-format table that can wrap the text well.
I have tried the method in this link. wrap long text in kable table column
But it fails.