How can I make a collapse with glue package using RMarkdown? - r

I've been trying to automate the results of some df table in latex using the glue and stargazer packages, but I haven't had any results (what I want is for the meaning "^{*}" to appear next to each value as it is in the table) to use then RMarkdown.
What I want to get:
My current ugly and error-prone fix:
library(dplyr)
library(glue)
library(stargazer)
X1 = c(4.70e1, 4.72e1, 4.76e1, 2.73e20)
X2 = c(4.67e1, 4.69e1, 4.77e1, 2.05e20)
tab.out = data.frame(X1, X2)
tab.out$max<-apply(tab.out, 1, max)
one = "1"
n.tab = tab.out %>%
mutate(test1 = if_else(tab.out$X2 < tab.out$max,
glue("\\textsuperscript{*} is $<<one>>$.", .open = "<<", .close = ">>"), #It doesn't work with ^{*}
glue("")))
Note: one was just to test the collapse because I tried glue_data as well as glue_collapse and it didn't work.
On the other hand, assuming the collapse works, how would I do to debug the latex code right? Because I tried with stargazer, xtable and textreg but in each of the functions it doesn't recognize "\, }, ^{*}".
n.tab = n.tab[c(1,2,4)]
stargazer(n.tab, summary = F, header = F)
What I got ?

I achieved this using the paste0 function as mentioned here and on the recommendation of #stefan but now I would like to automate the same function for n-columns
library(dplyr)
col.nam = c("AIC(n)", "HQ(n)", "SC(n)", "FPE(n)")
tab.out = data.frame(col.nam, X1, X2)
n.tab = tab.out %>%
mutate(test1 = if_else(tab.out$X1 < tab.out$X2,
paste0(X1,"$^{*}$"),
paste0(X1)),
test2 = if_else(tab.out$X2 < tab.out$X1,
paste0(X2,"\\textsuperscript{*}"),
paste0(X2)))%>%
select(col.nam, test1, test2)
colnames(n.tab) = c("Parámetros", "Lag 1", "Lag 2")
print(xtable::xtable(n.tab,
header = F,
caption = "asdasdasdasd",
label="table:tb1",
caption.placement = "top",
align="llcc"),
hline.after = c(-1,0),
include.rownames=FALSE,
include.colnames = TRUE,
add.to.row = list(pos = list(nrow(n.tab)),
command = paste("\\hline \n",
"\\multicolumn{3}{l}{\\footnotesize{$^{*}$Indica el orden de retraso seleccionado}} \\\\",
"\\multicolumn{3}{l}{\\footnotesize{\\textit{Elaboración: Los autores}}}",
sep = "")), comment=FALSE,
sanitize.text.function = function(x){x})

Related

R to latex: sanitize both % and \latexfunction at the same time

After some R computations I obtained a matrix that looks like that:
matrix <- cbind(c(00,01,02),c("some text","random stuff","special characters'"), c("0.12%","\\cellcolor{red!25}3.67%","1.61%"))
I am trying to export it to latex as follow:
file.name <- "file.name"
file.caption <- "file.caption"
print(xtable(matrix, align = c("l","r","r","r"),
label = paste("tab:", file.name, sep = "", collapse = NULL),
caption = file.caption),
type = "latex",
size="\\normalsize",
caption.placement = "top",
# file = paste("graphs/", file.name, ".tex", sep = "", collapse = NULL),
floating = FALSE,
tabular.environment = "longtable",
sanitize.text.function = function(x) x)
If I do not sanitize it, the pdf displays "\cellcolor{red!25}" (and obviously, I would prefer to have the cell colored). If I sanitize I can not typset the file.tex because of the "%".
I tried sanitize.text.function = function(x) x and sanitize.text.function = identity... without success.
Any idea?

Protected space and $ sign in R for latex extraction

I do multiple regression by group with a loop. I extract only 1 coefficient to which I attach stars according to this coef p-value.
Her is an example of my code:
for(i in 1:length(list)) {
# Equation
coef <- summary(lm(formula = var1 ~ var2 + var3 + var4,
data = subset(data.df, origin==var2[i])
),
)
# extraction
est <- coef$coefficients[2,1]
p <- coef$coefficients[2,4]
# Define notions for significance levels; spacing is important.
mystars <- ifelse(p < .001, "***",
ifelse(p < .01 , "** ",
ifelse(p < .05 , "* ",
" ")))
# past stars after estimate - put it in the matrix
est.mat[1,i] <- paste(sprintf('%.2f',est), mystars, sep = "", collapse = NULL)
# drop useless objects
rm(coef, est, t, p)
}
This works perfectly. Once done, I transfer my matrix est.mat into latex as follow:
print(xtable(est.mat, align = c("l","r","r","r","r","r","r"),
label = paste("tab:", file.name, sep = "", collapse = NULL),
caption = file.caption),
type = "latex",
size="\\normalsize",
caption.placement = "top",
file = paste("graphs/", file.name, ".tex", sep = "", collapse = NULL)
)
It works perfectly as well. The only problem is that, once printed in PDF the empty space after the stars defined in "mystar" are considered "un-existant" and therefore the coefficient numbers are not aligned, as illustrated below.
My question is then: How can I protect this space in "mystar" ?
One way to do this is to use "phantom" stars, which take up the same space as a star, but display nothing. I believe this modification of your code will do it:
mystars <- ifelse(p < .001, "***",
ifelse(p < .01 , "**\\phantom{*}",
ifelse(p < .05 , "*\\phantom{**}",
"\\phantom{***}")))
This will always leave space for three stars, so you might want to make it a little fancier by looking at the whole column first, and choosing how many phantom stars to add based on the most stars in the column. I'll leave that to you.
Edited to add: As described in Using xtable with R and Latex, math mode in column names?, print.xtable will escape the LaTeX macro, so it will display in the resulting PDF. But you can tell it not to, using argument sanitize.text.function:
print(xtable(est.mat, align = c("l","r","r","r","r","r","r"),
label = paste("tab:", file.name, sep = "", collapse = NULL),
caption = file.caption),
type = "latex",
size="\\normalsize",
caption.placement = "top",
file = paste("graphs/", file.name, ".tex", sep = "", collapse = NULL),
sanitize.text.function = function(x) x
)
This assumes that all of the table entries are legal LaTeX. If they are not, you may need a more complicated sanitization.

How to insert greek letter delta (∆) into header of flextable object?

I am using RMarkdown to create a word document (I need the output to be in .docx format).
I'd like to use flextable (or any other package) to format my headers properly.
I'm trying to get the greek symbol delta (∆) to display properly... it seems possible because in the help pages here (https://davidgohel.github.io/flextable/articles/format.html#display-function) the author successfully uses \u03BC to insert the "μ" symbol (and I can too if I use his code, below), but I can't get it to work for delta using \u2206 or \u0394, if I replace \u03BC with either code below. The code I'm using produces this table, but I want to replace the highlighted bit with delta.
This is what I get when I try, for example, \u2206.
Any suggestions?
library(flextable)
if( require("xtable") ){
mat <- round(matrix(c(0.9, 0.89, 200, 0.045, 2.0), c(1, 5)), 4)
mat <- xtable(mat)
ft <- xtable_to_flextable(x = mat, NA.string = "-")
print(ft$col_keys)
ft <- flextable::display(ft, i = 1, col_key = "X1",
pattern = "{{val}}{{pow}}", part = "header",
formatters = list(val ~ as.character("R"), pow ~ as.character("2") ),
fprops = list(pow = fp_text(vertical.align = "superscript", font.size = 8))
)
ft <- flextable::display(ft, i = 1, col_key = "X2",
pattern = "{{val}}{{pow}}", part = "header",
formatters = list(val ~ as.character("\u03BC"), pow ~ as.character("x") ),
fprops = list(pow = fp_text(vertical.align = "superscript", font.size = 8))
)
ft <- flextable::display(ft, i = 1, col_key = "rowname",
pattern = "{{val}}{{pow}}", part = "body",
formatters = list(val ~ as.character("y"), pow ~ as.character("t-1") ),
fprops = list(pow = fp_text(vertical.align = "subscript", font.size = 8))
)
ft <- set_header_labels(ft, X3 = "F-stat", X4 = "S.E.E", X5 = "DW", rowname = "")
ft <- autofit(ft)
ft
}
Update
I am getting closer thanks to a helpful suggestion from David, but (not being very familiar with flextable) I am getting strange behaviour when I try to modify the header in the way suggested:
library(magrittr)
library(flextable)
library(officer)
AICtable <- data.frame(Model = "test", Parameters = 9, AICc = 4000, dAICc = 0, w = 1)
v.epi.aic <- flextable(AICtable) %>%
font(fontname = "Times New Roman", part = "all") %>%
flextable::display(col_key = "dAICc", part = "header",
pattern = "{{D}}{{A}}{{cbit}}",
formatters = list(D ~ as.character("D"),
A ~ as.character("AIC"),
cbit ~ as.character("c") ),
fprops = list(D = fp_text(font.family = "Symbol"),
A = fp_text(font.family = "Times New Roman"),
cbit = fp_text(vertical.align = "subscript")))
v.epi.aic
Notice that column headers are now duplicated, and "AIC" appears before the "∆". The column names should be:
Model, Parameters, AICc, ∆AICc, w (and the "c" in the ∆AICc should be a subscript).
Please use "\u394" instead of "\u0394" to generate the capital delta symbol

Simplify R code to import big data as character

I am currently using the code below very often to import a big dataset into R and forcing it to treat everything as character in order to avoid the truncation of rows. The code seems to work well, but I was wondering whether any of you knows how it could be simplified or improved to so it doesn't get so repetitive each time I need to do it.
library(readr)
library(stringr)
dataset.path <- choose.files(caption = "Select dataset", multi = FALSE)
data.columns <- read_delim(dataset.path, delim = '\t', col_names = TRUE, n_max = 0)
data.coltypes <- c(rep("c", ncol(data.columns)))
data.coltypes <- str_c(data.coltypes, collapse = "")
dataset <- read_delim(dataset.path, delim = '\t', col_names = TRUE, col_types = data.coltypes)
like #Roland has suggested, you should write a function. here is one possibility:
foo <- function(){
require(readr)
dataset.path <- choose.files(caption = "Select dataset", multi = FALSE)
data.columns <- read_delim(dataset.path, delim = '\t', col_names = TRUE, n_max = 0)
data.coltypes <- paste(rep("c", ncol(data.columns)), collapse = "")
dataset <- read_delim(dataset.path, delim = '\t', col_names = TRUE, col_types = data.coltypes)
}
you can then just call foo() whenever you need to read a database in using this method.
your two liner:
data.coltypes <- c(rep("c", ncol(data.columns)))
data.coltypes <- str_c(data.coltypes, collapse = "")
can be collapsed into just one line and only using base R paste instead of str_c in the stringr package.

Xtable two columns using longtable customizations

This is a continuation of a question I posted earlier. I have a code.Rnw file in RStudio which I knit into a code.tex file using knit("code.Rnw") command.
I have a data frame that I am printing using the xtable command. In the example below, it is 20 rows. However, to save space, I am printing it out as two columns, each with 10 rows.
Below is my code:
\documentclass[11pt, a4paper]{article}
\usepackage[margin=3cm]{geometry}
\usepackage{longtable}
\begin{document}
<<echo=FALSE,results='asis'>>=
library(xtable)
set.seed(1)
spaceCol = rep(" ",10)
df1 = data.frame(student = letters[1:10], vals=runif(10, 1, 10))
df2 = data.frame(student = letters[11:20], vals=runif(10, 1, 10))
dfFull = data.frame(df1,spaceCol,df2)
names(dfFull) = c(" ","% Correct"," "," ", "% Correct")
row.names(dfFull) = NULL
x.big <- xtable(dfFull, label ='tabtwo',caption ='Caption for table with student scores')
print(x.big, tabular.environment ='longtable', floating = FALSE, include.rownames=FALSE)
#
\end{document}
This is what the output looks like:
I like the aesthetics of this output, especially because in the longtable format, this output will automatically page-break if need be. However, what I am trying to improve, is to make it more easy to visualize that this output is really two distinct columns.
To do that, I would like to add a space between the two columns, so the output looks more as follows:
However, if that proves impossible, then I could consider something like adding a vertical line to distinguish the two columns, as shown below:
How might this be possible given my limitation in using xtable?
\documentclass[11pt, a4paper]{article}
\usepackage{subfig}
\begin{document}
<<echo = FALSE>>=
library(xtable)
opts_chunk$set(
echo = FALSE,
results = 'asis'
)
set.seed(1)
mynames <- c("", "% Correct")
df1 = data.frame(letters[1:10], runif(10, 1, 10))
df2 = data.frame(student = letters[11:20], vals=runif(10, 1, 10))
colnames(df1) <- mynames
colnames(df2) <- mynames
#
\begin{table}\centering
\subfloat{
<<>>=
print(xtable(df1), floating = FALSE, include.rownames = FALSE)
#
} \hspace{2cm}
\subfloat{
<<>>=
print(xtable(df2), floating = FALSE, include.rownames = FALSE)
#
}
\caption{Caption for table with student scores} \label{tabtwo}
\end{table}
\end{document}
The only drawback is, that you cannot use longtable with this approach.
UPDATE: Here is an alternative that makes use of longtable. The trick is to use xtable for the contents of the table only and build the headline by hand, so you have full control over all lines etc. I decided to use an empty column for the space because making column 2 wider would make the horizontal lines look ugly.
\documentclass{article}
\usepackage{longtable}
\begin{document}
\thispagestyle{empty}
<<echo = FALSE>>=
library(xtable)
opts_chunk$set(
echo = FALSE,
results = 'asis'
)
set.seed(1)
df1 = data.frame(letters[1:10], runif(10, 1, 10))
df2 = data.frame(student = letters[11:20], vals=runif(10, 1, 10))
dfFull <- cbind(df1, NA, df2)
#
\begin{longtable}{lrl#{\hskip 2cm}lr} \cline{1-2} \cline{4-5}
& \% Correct & & & \% Correct \\ \cline{1-2} \cline{4-5}
<<>>=
print(xtable(dfFull), only.contents = TRUE, include.rownames = FALSE, include.colnames = FALSE, hline.after = NULL)
#
\cline{1-2} \cline{4-5}
\caption{Caption for table with studen scores} \label{tabtwo}
\end{longtable}
\end{document}
UPDATE2: Finally, a solution that uses longtable and doesn't involve creating half of the table "by hand". The trick is to remove all horizontal lines (hline.after = NULL) and than add \clines where required using add.to.row (inspired by this question).
\documentclass{article}
\usepackage{longtable}
\begin{document}
\thispagestyle{empty}
<<echo = FALSE, results = 'asis'>>=
library(xtable)
set.seed(1)
df1 = data.frame(letters[1:10], runif(10, 1, 10))
df2 = data.frame(letters[11:20], runif(10, 1, 10))
dfFull <- cbind(df1, NA, df2)
# To test "longtable", rbind data several times:
multiply <- 5
dfFull <- do.call("rbind", replicate(multiply, dfFull, simplify = FALSE))
colnames(dfFull) <- c("", "% Correct", "", "", "% Correct")
print(xtable(dfFull,
caption = "Caption for table with student scores",
label = "tabtwo",
align = c("l", # ignored (would apply to colnames)
"l", "r",
"l#{\\hskip 2cm}", # space between blocks
"l", "r")),
include.rownames = FALSE,
include.colnames = TRUE,
hline.after = NULL, # Remove all default lines. A line after the very last row remains, which is automatically added when using "longtable".
tabular.environment = "longtable",
floating = FALSE,
add.to.row = list(
pos = list(-1, 0),
command = rep("\\cline{1-2} \\cline{4-5}", 2))
)
#
\end{document}

Resources