Is there a way to fully align text to the top of collapsed rows in a Latex kable created with rMarkdown? - r-markdown

I have almost got the perfect table for a Latex report I am drafting with the kable package in rMarkdown. One thing I can't get quite right is the vertical alignment of the collapsed rows.
Using the sample code from the kableExtra documentation reproduces my problem:
collapse_rows_dt <- data.frame(C1 = c(rep("a", 10), rep("b", 5)),
C2 = c(rep("c", 7), rep("d", 3), rep("c", 2), rep("d", 3)),
C3 = 1:15,
C4 = sample(c(0,1), 15, replace = TRUE))
kbl(collapse_rows_dt, booktabs = T, align = "c") %>%
column_spec(1, bold=T) %>%
collapse_rows(columns = 1:2, latex_hline = "custom", custom_latex_hline = 1:2, valign = "top")
This almost works, so close...but the vertical alignment is not consistent across the columns. This makes it unreadable when the table runs over multiple pages.
valign= "bottom" works perfectly though.

The issue is with "booktabs = T".
With it set to "F", the vertical alignment is perfect.

Related

Is it possible to increase the line spacing for captions to 1.5 with kable?

As the title suggests, i am having trouble trying to set the line spacing for my table captions to 1.5 with the kable package while knitting the document to PDF with RMarkdown.
As of now, my codes looks like this:
kable(
table1,
booktabs = T,
align = 'l',
caption = "A very very very very very very very very very long caption that should have line spacing of 1.5."
) %>%
kable_styling(full_width = T)
Thanks in advance! :)
I've tried changing the spacing: to 1.5 under the YAML header but it is not reflected in the tables produced with kable()

Rmarkdown officer / officedown / flextables problem

I have the following rmd script. I've spent a few days trying to get this to work but I am failing miserably. Basically I need help with three things. I am happy to post three separate questions if needed.
The multicolumn options/code are completely ignored. The corporatetable.docx is in landscape and has a typical corporate style. I need to have a full width landscape -> two column landscape -> full width landscape. If I could get the two column landscape setup to work, the remaining style would be inherited by corporatetable.docx. If I could get help with only one - I would need this.
When I run the rmd it generates a word file but none of the corporate styles are in there. It just uses my word's default colors etc. The difference is very clear - no landscape, single column and blue instead of red. How do I correctly pass the officedown::rdocx_document: to reference my word file because it's clearly not picking it up and no warning or error is generated?
If you see in the second chunk I am using flextable to show two pictures (which are passed through params) in the word report and align them with some information. myft works but it prints the (temporary/volatile) path instead of showing the pictures in the report. For reference if I use knitr::include_graphics(c(params$x1,params$x2)) it works fine.
I'm really stuck on these. Any help is welcome.
---
title: "Title"
subtitle:
params:
x1: x1
x1_name: x1_name
x1_email : x1_email
x2: x2
x2_name: x2_name
x2_email : x2_name
output:
officedown::rdocx_document:
reference_docx: corporatetemplate.docx
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(officedown)
library(officer)
library(flextable)
knitr::opts_chunk$set(out.width = '100%', dpi=300)
```
<!---BLOCK_MULTICOL_START--->
This text is on column 1. Please work
```{r somecodechunk, echo=FALSE, out.width="75px", include=TRUE, strip.white=TRUE}
library(flextable)
# this works but prefer to use flextable
# if(all(!is.null(params))) {
# knitr::include_graphics(c(params$x1,params$x2))} else {
# }
myft <- data.frame(
"pic1" = rep("",3),
"details1" = c(params$x1_name,"+X XXX XXX X",params$x1_email),
"pic2" = rep("",3),
"details2" = c(params$x2_name,"+X XXX XXX X",params$x2_email)
)
myft <- flextable(myft)
myft <- merge_at(myft, i = 1:3, j = 1 )
myft <- merge_at(myft, i = 1:3, j = 3 )
myft <- compose(myft,i = 1, j = 1, value = as_paragraph(as_image(params$x1), part = "body"))
myft <- compose(myft,i = 1, j = 3, value = as_paragraph(as_image(params$x2), part = "body"))
autofit(myft)
#Ok this does not work because the pics are not shown
```
`r run_columnbreak()`
This text is on column 2. Please work
This text is on column 2. Please work
`r run_linebreak()`
<!---BLOCK_MULTICOL_STOP{widths: [4,4], space: 0.2, sep: true}--->
\pagebreak
Back to full width with some text
\pagebreak

How do I size a Shiny app within an R-Markdown document using the Tufte Template?

I am writing a report using R-Markdown and the Tufte Template. I have embedded Shiny apps within the report.
So far I have tried using "fig.width=" and "width=" in the chunck options to no avail, then tried ",
options = list(height = 600) " just before the closing parenthesis as suggested by B. Davis change dimensions of shiny app embedded in r markdown HTML and again no change.
hist_dist <- read.csv("hist_dist2.csv", check.names = FALSE)
inputPanel(
selectInput("dist", label = "Choose an ecosystem to explore historical disturbance regimes:", choices = hist_dist$`Ecosystem`, selected = "Northern Hardwoods Forest" , width = '70%')
)
renderPlotly({
ggplot(filter(hist_dist, Ecosystem == input$dist), aes(x=Disturbance, y=Acres)) +
geom_bar(stat="identity", fill = "darkslategrey") +
coord_flip() +
theme(legend.position='none') +
expand_limits(y=c(0, 60)) +
theme_bw() +
theme(panel.background = element_rect(colour = "grey", fill=NA, size=1),
text = element_text(family = "serif", size = 14),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black")
)
}
)
'''
I am able to change the width if I use other templates (non-Tufte), and are able to control the size of figures, just not Shiny apps.
I have been through the same situation. Tufte_html has something overwriting width behind the scene.
Here's my solution. Not the best but works. Basically you need to assign id to the plot and then change style from CSS.
Edit
output$my_plotly <- renderPlotly(❴❵)
Add
plotlyOutput("my_plotly") in the same chunk.
Write styles.css with
#my_plotly ❴ width: 55% !important❵
Tufte style uses 55% I believe.

Is there a way to have previous/next links at the bottom of shiny presentations?

I am working in RStudio and creating a markdown Shiny presentation (which I believe uses IOslides).
Currently the generated presentation doesn't have any navigational help, the user has to know they need to use left/right arrows to move to the next or previous slides. Even when deployed to server I don't see any arrows at the bottom of presentations.
I have searched through documentation and here to see if this is possible, but can't seem to find anything.
Is there some setting to include a Previous/Next type link at the bottom of every slide?
Process to create my presentation in R Studio:
New file > R Markdown > Shiny > Shiny presentation
The issue occurs even with the sample code when creating a new file - there are no navigation arrows
Published example (where there are no navigation arrows):
https://regolith.shinyapps.io/test
And the sample code (as generated by R studio):
---
title: "test"
author: ""
date: "24 January 2017"
output: ioslides_presentation
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
## Shiny Presentation
This R Markdown presentation is made interactive using Shiny. The viewers of the presentation can change the assumptions underlying what's presented and see the results immediately.
To learn more, see [Interactive Documents](http://rmarkdown.rstudio.com/authoring_shiny.html).
## Interactive Plot
```{r eruptions}
inputPanel(
selectInput("n_breaks", label = "Number of bins:",
choices = c(10, 20, 35, 50), selected = 20),
sliderInput("bw_adjust", label = "Bandwidth adjustment:",
min = 0.2, max = 2, value = 1, step = 0.2)
)
renderPlot({
hist(faithful$eruptions, probability = TRUE, breaks = as.numeric(input$n_breaks),
xlab = "Duration (minutes)", main = "Geyser eruption duration")
dens <- density(faithful$eruptions, adjust = input$bw_adjust)
lines(dens, col = "blue")
})
```
## Bullets
- Bullet 1
- Bullet 2
- Bullet 3
## R Output
```{r cars}
summary(cars)
```

Transforming/reshaping a dataset : Ranking College football teams for the last 50 years

I need some help transforming my dataset. I would appreciate any help or feedback.
I have data of College football scores for the last 50 years. I currently have a data frame like in picture 1, and I need to get a data frame similar to picture 2. The data frame I'm trying to get needs to have a concatenated list of all teams played each year, and also two columns that keep track of wins an losses respectively. The concatenated list must be specific for each year. So basically a data frame like picture 2, but has data for every year separately.
This is the code to get a cleaned up dataframe similar to the one I have in picture one.
# Make generic data frame and get data
practice = data.frame('a'=character(), 'b'=character(), 'c'= numeric(), 'd'=character(), 'e'= numeric(), 'f'=character())
widths = c(10, 28, 5, 28, 3, 19)
years = 1960:2010
for (i in years){
football_page = paste('http://homepages.cae.wisc.edu/~dwilson/rsfc/history/howell/cf', i, 'gms.txt',sep = '')
get_data = read.fwf(football_page, widths)
practice = rbind(practice, get_data)
}
heading = list('DATE', 'AWAY TEAM', 'AWAY SCORE', 'HOME TEAM', 'HOME SCORE', 'LOCATION')
colnames(practice) = heading
# Fixing season dates
practice = cbind('SEASON'=numeric(nrow(practice)),practice)
fix_date = matrix(0, nrow = nrow(practice))
for (j in 1:nrow(fix_date)){
fix_date[j,1] = substr(practice[j,2],7,10)
}
fix_date = as.numeric(fix_date)
practice$SEASON = fix_date
for (j in 1:nrow(practice)){
if (grepl('01/.......', practice[j,2]))
practice[j,1] = practice[j,1]-1
}
#fix names
practice[,3]=gsub(' ','',practice[,3])
practice[,5]=gsub(' ','',practice[,5])
#drop location and columns
practice = practice[, -7]
practice = practice[, -2]
The data set is called practice.
I can't thoroughly test it without a sample of your data or something like it, but I think this would do the job.
# Create a function to get win and loss counts by season for a single team
teamsum <- function(teamname) {
require(dplyr)
df <- practice %>%
# Reduce the data set to games involving a single team
filter(AWAY TEAM==teamname | HOME TEAM==teamname) %>%
# Create a 0/1 indicator for whether or not that team won each of those games. Note
# that ties will get treated as losses here; you could change that with a more
# complicated set of if/else statements
mutate(team = teamname,
win = ifelse((AWAY TEAM==teamname & AWAY SCORE > HOME SCORE) |
(HOME TEAM==teamname & HOME SCORE > AWAY SCORE), 1, 0)) %>%
# Group the data by season for the summing to follow
group_by(SEASON) %>%
# Reduce the data to a table with counts of wins and losses by season
summarise(wins = sum(win),
losses = n() - sum(win)) %>%
# Add the team name as an id column to that summary table. In dplyr piping, '.' is
# the object created by the preceding step in the pipeline -- here, that summary
# table of wins and losses.
cbind(team = rep(teamname, nrow(.)), .) %>%
return(df)
}
# Apply that function to a vector of unique team names to make a list with
# tables of win & loss counts by season for each team in the original data.
# This version assumes that every team was the home team at least once.
teamlist <- lapply(unique(practice[,"HOME TEAM"]), teamsum)
# Merge the elements of that list into a single data frame. You could rbind, too.
df <- Reduce(function(...) merge(...), teamlist)
Another dplyr answer
I used your code to get the dataset and then I duplicated the team columns to use as key for reshaping the dataset, you can probably use the same concept to achieve the objective in base R.
library(dplyr)
library(tidyr)
practice_2 <- practice %>%
mutate(home = `HOME TEAM`,
away = `AWAY TEAM`) %>%
# transform dataset to long format with `tidyr::gather()`
gather(LOC, TEAM, 6:7) %>%
group_by(SEASON, TEAM) %>%
mutate(won = ifelse(LOC == "home",
as.numeric(`HOME SCORE` > `AWAY SCORE`),
as.numeric(`AWAY SCORE` > `HOME SCORE`)),
lost = ifelse(LOC == "home",
as.numeric(`HOME SCORE` <= `AWAY SCORE`),
as.numeric(`AWAY SCORE` <= `HOME SCORE`)),
op = ifelse(LOC == "home", `AWAY TEAM`, `HOME TEAM`)) %>%
summarise(WINS = sum(won, na.rm = TRUE),
LOSSES = sum(lost, na.rm = TRUE),
OPPONENTS = list(unique(op)))