Several lines with different style in Caption in both html and docx - flextable - html

I need to show data caption, computer name and period in the header of table.
I have also requirements: zebra theme, merging cells if needed. That's why I chose flextable.
Here is my code:
library(officer) # border settings library
library(flextable) # drawing tables library
library(dplyr)
Caption <- "<b><big>Computer01.domain.com</big></b><br>Network Interface<br>Gbit Total/sec<br><small>2021-05-14 18:04 to 2021-05-25 13:29</small>"
bold_border <- fp_border(color="gray", width =2)
std_border <- fp_border(color="gray")
stub <- "2021-05-14 01:40 to 2021-05-17 08:26"
table_data <- data.frame (
Instance = c("Intel[R] Ethernet 10G",
"Intel[R] Ethernet Converged Network Adapter _1",
"Intel[R] Ethernet Converged Network Adapter _2",
"Intel[R] Ethernet 10G",
"Intel[R] Gigabit"),
Max = c(2.45, 2.41, 2.29, 2.17, 0),
Avg = c(0.15, 0.15, 0.15, 0.17, 0)
)
table <- table_data %>% flextable() %>%
set_caption(caption = Caption , html_escape = F) %>%
bg(bg = "#579FAD", part = "header") %>%
color(color = "white", part = "header") %>%
theme_zebra(
odd_header = "#579FAD",
odd_body = "#E0EFF4",
even_header = "transparent",
even_body = "transparent"
) %>%
set_table_properties(width = 1, layout = "autofit") %>%
hline(part="all", border = std_border ) %>%
vline(part="all", border = std_border ) %>%
border_outer( border = bold_border, part = "all" ) %>%
fix_border_issues() %>%
set_header_labels(
values = list(Instance = InstanceName ) ) %>%
flextable::font (part = "all" , fontname = "Calibri")
save_as_docx( table, path = file.path("c:\\temp", "test01.docx") )
save_as_html (table, path = file.path("c:\\temp", "test01.html"))
Here is what I got in html which is okay for me:
But in docx format my header style is not applied:
How can I create header like I did for html that can be saved to both html and docx?
If I have to create separate tables - one for html, other for docx - it's not so good but acceptable options. That case my question how to create header I made in html but for docx format?

Related

how to get background color in html variable for a shiny app in r?

I am creating a shiny app and trying to get top two fields (Name & location) of the html popup to have a orange background color.
library(shiny)
library(shinydashboard)
library(tidyverse)
library(leaflet)
# library(htmlwidgets)
# library(htmltools)
library(readxl)
library(RCurl)
URL <- "https://www.mohfw.gov.in/pdf/PMJAYPRIVATEHOSPITALSCONSOLIDATED.xlsx"
download.file(URL, destfile = "../../timesnow_PMJAYPRIVATEHOSPITALSCONSOLIDATED.xlsx",method = "curl")
# Data
ind_vaccination_leaflet <- readxl::read_xlsx(path = "../../timesnow_PMJAYPRIVATEHOSPITALSCONSOLIDATED.xlsx",
sheet = 1)
# Creating variable with html tags & background doesn't work
ind_vaccination_leaflet <- ind_vaccination_leaflet %>%
mutate(label_display = paste(
"<body style='background-color:orange;'>",
"<h2>", "Center: ", ind_vaccination_leaflet$`Name of the Vaccination Site*`, "</h2>",
"<h3>",ind_vaccination_leaflet$`District*`, ", ", ind_vaccination_leaflet$`State*`, "</h3>",
"</body>",
"<p>", "Address: ", ind_vaccination_leaflet$Address, ", ", ind_vaccination_leaflet$`PinCode*`, "</p>",
"<p>", "Mobile: ", ind_vaccination_leaflet$`Mobile Number`, "</p>",
"<p>", "Contact Person: ", ind_vaccination_leaflet$`Contact Person`, "</p>"
)
)
Issue: When I plot it using below code then I don't get the orange background in the first two rows of the popup:
m <- leaflet() %>%
setView(lat = 26.64510, lng = 80.17012, zoom = 5) %>%
addTiles(group = "OSM") %>%
addProviderTiles(providers$CartoDB.DarkMatter, group = "Dark") %>%
addProviderTiles(providers$CartoDB.Positron, group = "Light") %>%
addProviderTiles("Stamen.Terrain", group = "Terrain") %>%
addProviderTiles("Esri.WorldImagery", group = "WorldImagery") %>%
addLayersControl(baseGroups = c("OSM","WorldImagery","Dark","Light","Terrain"))
m %>%
addCircleMarkers(
lng = ind_vaccination_leaflet$lon,
lat = ind_vaccination_leaflet$lat,
label = lapply(ind_vaccination_leaflet$label_display, htmltools::HTML),
color = "midnightblue",
weight = 1,
radius = 8
)%>%
addMiniMap(tiles = providers$OpenStreetMap, width = 120, height=80)
I am not really a coder nor ui/html person so not sure where is it going wrong.
Try switching body to div.
You can experiment with HTML code much easier in an online editor, e.g. this one

R: Converting ggplot objects to interactive graphs

I am using the R programming language. I am trying to take different types of graphs (bar graphs, pie charts) and put them on the same page. I generated some fake data and made several graphs - then I put them together (see : Combining Different Types of Graphs Together (R))
library(dplyr)
library(ggplot2)
library(cowplot)
library(gridExtra)
library(plotly)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
var <- rnorm(731,10,10)
group <- sample( LETTERS[1:4], 731, replace=TRUE, prob=c(0.25, 0.22, 0.25, 0.25) )
data = data.frame(date, var, group)
data$year = as.numeric(format(data$date,'%Y'))
data$year = as.factor(data$year)
###Pie
Pie_2014 <- data %>%
filter((data$year == "2014")) %>%
group_by(group) %>%
summarise(n = n())
Pie_2014_graph = ggplot(Pie_2014, aes(x="", y=n, fill=group)) +
geom_bar(stat="identity", width=1) +
coord_polar("y", start=0) +ggtitle( "Pie Chart 2014")
Pie_2015 <- data %>%
filter((data$year == "2015")) %>%
group_by(group) %>%
summarise(n = n())
Pie_2015_graph = ggplot(Pie_2015, aes(x="", y=n, fill=group)) +
geom_bar(stat="identity", width=1) +
coord_polar("y", start=0) +ggtitle( "Pie Chart 2015")
Pie_total = data %>%
group_by(group) %>%
summarise(n = n())
Pie_total_graph = ggplot(Pie_total, aes(x="", y=n, fill=group)) +
geom_bar(stat="identity", width=1) +
coord_polar("y", start=0) +ggtitle( "Pie Chart Average")
###bars
Bar_years = data %>%
group_by(year, group) %>%
summarise(mean = mean(var))
Bar_years_plot = ggplot(Bar_years, aes(fill=group, y=mean, x=year)) +
geom_bar(position="dodge", stat="identity") + ggtitle("Bar Plot All Years")
Bar_total = data %>%
group_by(group) %>%
summarise(mean = n())
Bar_total_plot = ggplot(Bar_total, aes(x=group, y=mean, fill=group)) +
geom_bar(stat="identity")+theme_minimal() + ggtitle("Bar Plot Average")
#assembling the graphs can be done two different ways
#first way
g1 <- grid.arrange(Pie_2014_graph, Pie_2015_graph , Pie_total_graph, nrow = 1)
g2 <- grid.arrange(Bar_total_plot, Bar_years_plot, nrow = 1)
g = grid.arrange(g1, g2, ncol = 1)
#second way
# arrange subplots in rows
top_row <- plot_grid(Pie_2014_graph, Pie_2015_graph, Pie_total_graph)
middle_row <- plot_grid(Bar_years_plot, Bar_total_plot)
# arrange our new rows into combined plot
p <- plot_grid(top_row, middle_row, nrow = 2)
p
From here, I am trying to use the plotly::ggplotly() command to make the above output "interactive" (move the mouse over the graphs and see labels). I know that this works for individual plots:
ggplotly(Bar_years_plot)
However, this command does not seem to work with the "cowplot" and the "gridExtra" outputs:
#gridExtra version:
ggplotly(g)
Error in UseMethod("ggplotly", p) :
no applicable method for 'ggplotly' applied to an object of class "c('gtable', 'gTree', 'grob', 'gDesc')"
#cowplot version: (produces empty plot)
ggplotly(p)
Warning messages:
1: In geom2trace.default(dots[[1L]][[1L]], dots[[2L]][[1L]], dots[[3L]][[1L]]) :
geom_GeomDrawGrob() has yet to be implemented in plotly.
If you'd like to see this geom implemented,
Please open an issue with your example code at
https://github.com/ropensci/plotly/issues
2: In geom2trace.default(dots[[1L]][[1L]], dots[[2L]][[1L]], dots[[3L]][[1L]]) :
geom_GeomDrawGrob() has yet to be implemented in plotly.
If you'd like to see this geom implemented,
Please open an issue with your example code at
https://github.com/ropensci/plotly/issues
Does anyone know if there is a quick way to use the ggplotly() function for objects created with "gridExtra" or "cowplot"?
I know that with a bit of work, it might be possible using "htmltools":
library(htmltools)
doc <- htmltools::tagList(
div(Pie_2014_graph, style = "float:left;width:50%;"),
div(Pie_2015_graph,style = "float:left;width:50%;"),
div(Pie_total_graph, style = "float:left;width:50%;"),
div(Bar_years_plot, style = "float:left;width:50%;"),
div(Bar_total_plot, style = "float:left;width:50%;"))
save_html(html = doc, file = "out.html")
But I am not sure how to do this.
Can someone please show me how to make the collections of graphs interactive either using ggplotly() or with htmltools()?
Thanks.
You should apply ggplotly() to the individual graphs, not the collection graphs.
For example:
Pie_2014_graph = ggplotly(ggplot(Pie_2014, aes(x="", y=n, fill=group)) +
geom_bar(stat="identity", width=1) +
coord_polar("y", start=0) +ggtitle( "Pie Chart 2014") )

column_spec crashing PDF in Rmd output to both PDF and html in shiny app

EDIT: Because I had set the format options in a global function, I have to set either latex_options or bootstrap_options in the kable_styling() call. I was using bootstrap_options which wasn't being read by the latex. My work-around is to make the tables twice, once in a chunk for html, and once in a chunk for latex. Not great, but it works if I click the Knit button and choose Knit to PDF. However, it throws the original error when I try to run it in the shiny app.
I have created a test version (MiniTest) of my project. What I need to do is have a shiny app run with a tab that will produce an html file for a user-chosen (reactive) Country, and provide an Excel download (I have that working so kept it out of this example), and a PDF download. I knit in an .Rmd which chooses the format and allows for parameterization. (The shiny part was set up by someone else, from whom I took over this project when they left before finishing it.)
I use kable and kableExtra to create and format tables, as I heard it words for both html and LaTeX output. The HTML is more as less as I want it. I can knit either html or PDF, and it runs, BUT when in the shiny app, only the html portion works. I think I have narrowed down the PDF issue(s) to column_spec crashing the download. If I comment out the column_spec lines in t01 and t02, the Download PDF runs. But I need that formatting. I'm sorry, but I've lost track of all the sites I have searched.
In global.R, I set:
countries <- c("ABC", "DEF", "GHI", "JKL")
In the .Rmd, I have YAML set up (with two-space indents for Country and output types):
params:
Country: ABC
output:
pdf_document: default
html_document: default
Relevant .Rmd chunks and inline code include:
knitr::opts_chunk$set(echo = FALSE)
options(knitr.table.format = function() {
if (knitr::is_latex_output()) "latex" else "html"
})
library(shiny)
library(htmlwidgets)
library(shinythemes)
library(shinydashboard)
library(shinyjs)
library(shinycssloaders)
library(markdown)
library(tidyr)
library(tidyverse)
library(janitor)
library(kableExtra)
options(scipen = 999)
mini <- mtcars %>%
tibble::rownames_to_column(var = "car") %>%
mutate(Country = c(rep("ABC", 8), rep("DEF", 8), rep("GHI", 8), rep("JKL", 8)))
## https://bookdown.org/yihui/rmarkdown-cookbook/font-color.html
colorize <- function(x, color) {
if (knitr::is_latex_output()) {
## hack setting color='blue' instead of a hexcode with # that breaks the LaTeX code
sprintf("\\textcolor{%s}{%s}", color = 'blue', x) ## works, but isn't right blue
} else if (knitr::is_html_output()) {
sprintf("<span style='color: %s;'>%s</span>", color, x)
} else x
}
## make two tables with `kable` and `kableExtra`
new_title <- paste0("Dynamically Changing Country Name in column", params$Country)
t01 <- mini %>%
filter(Country == params$Country) %>%
select(car, mpg:hp) %>%
rename({{new_title}} := car) %>%
kable(align = c("l", "c", "c", "c", "c")) %>%
kable_styling(full_width = FALSE, position = "left", bootstrap_options = c("striped", "condensed")) %>%
column_spec(1, bold = TRUE) %>%
column_spec(2:3, width = "5em") %>%
row_spec(0, color = "#2A64AB") %>%
row_spec(6, bold = TRUE)
t02_title <- paste0(params$Country, " Table with Dollar Signs in Var Names")
t02 <- mini %>%
filter(Country == params$Country) %>%
select(car, drat, wt) %>%
mutate(car = case_when(car == "Mazda RX4" ~ "Mazda RX4 (US\\$)*", TRUE ~ as.character(car))) %>%
## want to blank out column names - removing them entirely would be best, but it fails
kable(align = c("l", "r", "c"), escape = TRUE, col.names = c("", "", "")) %>%
kable_styling(full_width = FALSE, position = "left", bootstrap_options = c("striped", "condensed")) %>%
column_spec(1, bold = TRUE) %>%
column_spec(2, width = "10em") %>%
footnote(general = "*Never smart to start with an asterisk, but here we are", general_title = "")
## make two charts with `ggplot2`
chart1 <- mini %>%
filter(Country == params$Country) %>%
select(car, mpg:hp) %>%
ggplot2::ggplot(mapping = aes(x = mpg)) +
geom_col(aes(y = `cyl`, fill = "cyl"), color = "black")
c1_title <- paste0("Some fab title here for ", params$Country)
chart2 <- mini %>%
filter(Country == params$Country) %>%
select(car, vs:carb) %>%
ggplot2::ggplot(mapping = aes(x = carb)) +
geom_col(aes(y = `gear`, fill = "gear"), color = "black")
c2_title <- paste0("Another chart, ", params$Country)
## make a "tiny" LaTeX environment that is only generated for LaTeX output, with chunk setting `include = knitr::is_latex_output()`.
knitr::asis_output('\n\n\\begin{tiny}')
## Table 1
t01
I expect a PDF to pop up, but instead a Save File box pops up asking to save "DownloadPDF" with no file extension. The ui.R is supposed to name it as "FactCountryName.pdf" where "CountryName" is input from the Country the user chose in the drop-down list. Regardless of whether I choose Save (nothing happens) or Cancel, my R throws the following error:
```
! LaTeX Error: Illegal character in array arg.
```
If I comment out the line column_spec(1, bold = TRUE) %>%, the error changes to:
```
! Use of \#array doesn't match its definition.
\new#ifnextchar ...served#d = #1\def \reserved#a {
#2}\def \reserved#b {#3}\f...
l.74 ...m}|>{\centering\arraybackslash}p{5em}|c|c}
```
Please help!
Turns out that using the Knit button in R automatically loads the required LaTeX packages, such as booktabs. Running the file in the Shiny app was not loading all the packages needed. All I had to do was specifically call the extra packages in the YAML (which I found by looking at the .tex file made from the PDF through Knit button).
---
params:
Country: ABC
header-includes:
- \usepackage{booktabs}
- \usepackage{longtable}
- \usepackage{array}
- \usepackage{multirow}
- \usepackage{wrapfig}
- \usepackage{float}
- \usepackage{colortbl}
- \usepackage{pdflscape}
- \usepackage{tabu}
- \usepackage{threeparttable}
- \usepackage{threeparttablex}
output:
pdf_document:
keep_tex: true
html_document: default
---

Post local image into a popup using leaflet and R

I've been trying like crazy to add local images (as in image files in my computer) into my leaflet map using R. I have plotted around 500 coordinates analyzing some images and I wish to show that specific image when clicking (popup).
leaflet(pics) %>%
addTiles() %>%
addCircleMarkers(
fillOpacity = 0.8, radius = 5,
lng = ~GPSLongitude, lat =~GPSLatitude,
color = ~pal(Married),
popup = ~SourceFile, # WISH TO ADD EMBEDDED LOCAL IMAGE IN HERE
label = mapply(function(x, y) {
HTML(sprintf("<em>%s</em></br> %s", htmlEscape(x), htmlEscape(y)))},
pics$Address, pics$DateTimeOriginal, SIMPLIFY = F),
labelOptions = lapply(1:nrow(pics), function(x) {
labelOptions(direction='auto')
}))
I am attaching 2 screenshots: one hovering the mouse and the other one clicking on a specific place. Ideally, I'd wish to show the image and the image file name when I click on each one. Is that possible?
I can also show you an RPub with the example: http://rpubs.com/laresbernardo/photomap
Hope you can help me. Thanks!
_________________________ UPDATE _________________________
All code used for this example. Basically I scan for all images with geotags, bring the address to add on a label and then plot all coordinates. When I click on a coordinate I wish to see that picture.
wd <- "/Users/bernardo/Dropbox (Personal)/Documentos/R/R Mapping/GPS Photos"
# ------------------------------------------- get the pics with geotags
library(exifr)
library(dplyr)
library(lubridate)
library(beepr)
library(maps)
time <- Sys.time(); print(time)
setwd("/Users/bernardo/Dropbox (Personal)/Imágenes")
files <- list.files(pattern = "*.jpg|*.JPG|*.png|*.PNG", recursive=T)
exif <- read_exif(files, tags = c("SourceFile", "DateTimeOriginal", "GPSLongitude", "GPSLatitude"))
pics <- exif %>% filter(!is.na(GPSLongitude)) %>%
mutate(DateTimeOriginal = ymd_hms(DateTimeOriginal))
pics$Owner <- ifelse(grepl("iPhone Maru", pics$SourceFile), "Maru", "Ber")
pics$Married <- ifelse(as.Date(pics$DateTimeOriginal) >= '2016-04-30', TRUE, FALSE)
pics$Country <- maps::map.where(database="world", pics$GPSLongitude, pics$GPSLatitude)
#lares::freqs(pics %>% filter(!is.na(Country)), Country)
# Save pics with geotags
setwd(wd)
write.csv(pics, "with_geotags.csv", row.names = F)
print(Sys.time() - time)
beepr::beep()
# ------------------------------------------- get the addresses from files
# GET ALL ADDRESSES
library(ggmap)
options(warn=-1)
setwd(wd)
pics <- read.csv("with_geotags.csv")
addresses <- read.csv("with_address.csv")
pics_to_search <- pics %>% filter(!SourceFile %in% addresses$SourceFile)
print(paste0("Without address: ",round(100 * nrow(pics_to_search)/nrow(pics), 2),"% | ", nrow(pics_to_search)))
out <- data.frame()
for (i in 1:nrow(pics_to_search)) {
Address <- revgeocode(cbind(pics_to_search$GPSLongitude, pics_to_search$GPSLatitude)[i,], output="address")[1]
if (!is.na(Address)) {
out <- rbind(out, cbind(SourceFile=as.character(pics_to_search$SourceFile[i]), Address))
print(paste(i, Address, sep=" - "))
}
}
# Save pics with geotags
pics_with_address <- rbind(out, addresses)
write.csv(pics_with_address, "with_address.csv", row.names = F)
# ------------------------------------------- Map all coordinates with leaflet
setwd(wd)
library(leaflet)
library(htmltools)
library(mapview)
pics <- read.csv("with_geotags.csv")
address <- read.csv("with_address.csv")
pal <- colorFactor(c("green4", "navy"), domain = c(FALSE, TRUE))
pics <- left_join(pics, address, by=c("SourceFile"))
pics$Content <- paste("Dirección:","<em>", pics$Address,"</em>", "<br/> Fecha:", as.Date(pics$DateTimeOriginal))
leaflet(pics) %>%
addTiles() %>%
addCircleMarkers(
fillOpacity = 0.8, radius = 5,
lng = ~GPSLongitude, lat =~GPSLatitude,
color = ~pal(Married),
popup = popupImage(as.character(pics$SourceFile), src = "local"),
label = mapply(function(x, y) {
HTML(sprintf("<em>%s</em></br> %s", htmlEscape(x), htmlEscape(y)))},
pics$Address, pics$DateTimeOriginal, SIMPLIFY = F),
labelOptions = lapply(1:nrow(pics), function(x) {
labelOptions(direction='auto')
}))
But...
I even installed the latest version with devtools::install_github("r-spatial/mapview#develop")
With no reproducible example it is hard, but takes this for instance:
library(leaflet)
library(mapview)
# make-up dataset
data_df <- data.frame(lat = as.numeric(c("35.68705", "35.88705")), long = as.numeric(c("51.38", "53.35")))
# Loaded random pictures on my laptop
images <- c("/PathToImage1/download.jpeg",
"/PathToImage2/download1.jpeg")
leaflet(data_df) %>%
addTiles() %>%
addCircleMarkers(
fillOpacity = 0.8, radius = 5,
lng = ~long, lat =~lat,
popup = popupImage(images)
)
Click on each point to see a different image. Make sure to load your images in the same order as your data frame.
Finally after lots of hours wasted in this problem, I managed to fix the issue. Thanks to #MLavoie and #TimSalabim3 (via Twitter) for the support.
This was it: if you are running macOS, you should have installed a driver called gdal. I literally just installed it, ran the original script and it worked. Don't know what that gdal does but it really did the job!

htmlwidgets side by side in html?

Say I have two htmlwidgets
# Load energy projection data
# Load energy projection data
library(networkD3)
URL <- paste0(
"https://cdn.rawgit.com/christophergandrud/networkD3/",
"master/JSONdata/energy.json")
Energy <- jsonlite::fromJSON(URL)
# Plot
sankeyNetwork(Links = Energy$links, Nodes = Energy$nodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
units = "TWh", fontSize = 12, nodeWidth = 30)
and
library(leaflet)
data(quakes)
# Show first 20 rows from the `quakes` dataset
leaflet(data = quakes[1:20,]) %>% addTiles() %>%
addMarkers(~long, ~lat, popup = ~as.character(mag))
And I want to put them side by side in an html page. How can I do this? Could I use an iframe? Other?
There are lots of ways to answer this. Often sizing and positioning will vary based on who authored the htmlwidget, so you might need to experiment a little. The easiest way if you don't plan to use a CSS framework with grid helpers will be to wrap each htmlwidget in tags$div() and use CSS. You also might be interested in the very nice new flexbox-based dashboard package from RStudio http://github.com/rstudio/flexdashboard.
# Load energy projection data
# Load energy projection data
library(networkD3)
URL <- paste0(
"https://cdn.rawgit.com/christophergandrud/networkD3/",
"master/JSONdata/energy.json")
Energy <- jsonlite::fromJSON(URL)
# Plot
sn <- sankeyNetwork(Links = Energy$links, Nodes = Energy$nodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
units = "TWh", fontSize = 12, nodeWidth = 30,
width = "100%")
library(leaflet)
data(quakes)
# Show first 20 rows from the `quakes` dataset
leaf <- leaflet(data = quakes[1:20,]) %>% addTiles() %>%
addMarkers(~long, ~lat, popup = ~as.character(mag))
library(htmltools)
browsable(
tagList(list(
tags$div(
style = 'width:50%;display:block;float:left;',
sn
),
tags$div(
style = 'width:50%;display:block;float:left;',
leaf
)
))
)