Plot colours in HTML differ from within RStudio after knit - html

I am trying to generate a shareable HTML document generated from an R Script in RStudio.
The script makes use of interactive plots generated from networkD3 and collapsibleTree packages. In the RStudio viewer, the colour scheme for these plots is highly visible; colours such as blue and red for the items.
However, when rendered in HTML, the colour scheme becomes a washed out grey: practically white on white background, which makes it too hard to see or use.
Can I specify plot colours in the RScript using a knitr passthrough, I don't know, something like:
#+ colourscheme(RdBu)
or do I need to generate some kind of CSS file to control plot colours? I am unclear and not very knowledgeable in this HTML area, and a little confused why the colours would change at all!
Thanks in advance for any help.
-- edit (example provided)
In response to the request below, I've generated a tiny example. However (!) when this is rendered, it retains the correct colour scheme. I'm unclear now what it is causing this; colours are linked to "gp" in my main diagram, and I have only 3 groups so should see 3 colours. I'm not able to provide a full example due to size (data limitations), so here's the outline:
nodes <- data.frame(Name = c('Alpha', 'Beta', 'Charlie'),
ID = c(0,1,2),
gp = c(1,1,2),
n = c(10,15,20))
links <- data.frame(x = c(0, 0, 0, 1, 1, 2, 2),
y = c(0, 1, 2, 1, 2, 0, 2),
n = c(8, 9, 8, 9, 8, 9, 8))
require(networkD3)
require(RColorBrewer)
forceNetwork(height = 200, width = 400,
Links = links, Nodes = nodes,
Source = "x", Target = "y", Value = "n", # From Links df
NodeID = "Name", Group = "gp", Nodesize = "n", # From Nodes df
arrows = T,
linkWidth = JS("function(d) { return Math.sqrt(d.value); }"),
#linkWidth = JS(" d.value"),
radiusCalculation = JS(" d.nodesize"),
charge = -10,
fontSize = 16,
colourScale = JS("d3.scaleOrdinal(d3.schemeCategory10);"),
opacity = 0.9,
bounded = T)
I'm guessing (?) that there's a certain set of conditions that triggers the colours to fail.

I'm pretty sure this happens because collapsibleTree is adding CSS that affects the elements created by forceNetwork. Can you try putting this minimal example in a .Rmd file and knit it to see if shows a similar problem...
---
output: html_document
---
```{r echo=FALSE}
nodes <- data.frame(NodeID = c("Alpha", "Beta", "Charlie"),
Group = c(1, 2, 3),
Nodesize = c(10, 15, 20))
links <- data.frame(Source = c(0, 0, 1, 2),
Target = c(1, 2, 2, 0),
Value = c(9, 8, 8, 9))
library(networkD3)
forceNetwork(Links = links, Nodes = nodes,
Source = "Source", Target = "Target", Value = "Value",
NodeID = "NodeID", Group = "Group", Nodesize = "Nodesize",
colourScale = JS("d3.scaleOrdinal(d3.schemeCategory10);"),
width = 100, height = 100)
```
```{r echo=FALSE}
library(collapsibleTree)
collapsibleTree(warpbreaks, c("wool", "tension", "breaks"),
width = 100, height = 100)
```
if so, try installing the dev version of collapsibleTree with devtools::install_github('AdeelK93/collapsibleTree') and then try it again and see if the problem goes away (and your other problem). They added namespaced css in this commit which hasn't made it into a CRAN release yet.

Related

Is it possible to arrange graphs and filters in an R plot output?

I have created a small dashboard using bscols( from the crosstalkpackage. It consists of plotly graphs and their respective filter_checkboxes.
It looks pretty messy now, as the filters are not vertically aligned with their corresponding plots.
HTML_graphic
As indicated, I would like the first two checkbox sets to appear next to the second line graph (nothing to appear next to the first line graph); and the second two checkbox sets to appear next to the third line graph.
Also, I would like to create some vertical space between the three elements, as indicated by the brown and black horizontal lines.
The best solution would be to set the height of the html elements inside the bscols() command. Because in the future, I would like to programmatically save multiple of these outputs using htmltools::save_html.
The next best would be to have the output of that command somehow converted to html and add html code like line breaks or heights.
Neither I know how to do.
I came across this related question but it is unanswered: Arrange crosstalk graphs via bscols
Any suggestions on how to solve my problem?
My code
{r 002_Auto App Doc Vol_Invoice group delta plot - plot code, echo = FALSE}
# Setup of the legend for invoice plot
invoice_plot_legend <- list(
font = list(
family = "sans-serif",
size = 12,
color = "#000"),
title = list(text="<b> Delta previous month by division </b>"),
bgcolor = "#E2E2E2",
bordercolor = "#FFFFFF",
borderwidth = 2,
layout.legend = "constant",
traceorder = "grouped")
# The Shared Data format is needed for crosstalk to be able to filter the dataset upon clicking the checkboxes (division filters):
shared_invoice <- SharedData$new(Auto_App_Doc_Vol_invoiceg_plotting_tibble)
shared_invoice_KPI <- SharedData$new(Auto_App_Doc_Vol_KPI)
shared_abs <- SharedData$new(Auto_App_Doc_Vol_plotting_tibble_diff_abs)
# Setup of a bscols html widget; widths determines the widths of the input lists (here, 2: the filters, 10: the plot and legend)
# Overall KPI and invoice group plot
library(htmlwidgets)
crosstalk::bscols(
widths = c(2, 10),
list(
crosstalk::filter_checkbox("Division",
label = "Division",
sharedData = shared_invoice,
group = ~Division),
crosstalk::filter_checkbox("Rechnungsgruppe",
label = "Invoice group",
sharedData = shared_invoice,
group = ~Rechnungsgruppe),
crosstalk::filter_checkbox("Rechnungsgruppe",
label = "Invoice group",
sharedData = shared_abs,
group = ~Rechnungsgruppe),
crosstalk::filter_checkbox("Division",
label = "Division",
sharedData = shared_abs,
group = ~Division)
)
,
list(
plot_ly(data = shared_invoice_KPI, x = ~Freigabedatum_REAL_YM, y = ~KPI_current_month, meta = ~Division,
type = "scatter",
mode = "lines+text",
text = ~KPI_current_month,
textposition='top center',
hovertemplate = "%{meta}",
color = ~Diff_KPI_pp)
%>%
layout(legend = invoice_plot_legend,
title = "Automatically Approved Document Volume",
xaxis = list(title = 'Release date'),
yaxis = list(title = '%'))
,
plot_ly(data = shared_invoice, x = ~Freigabedatum_REAL_YM, y = ~n,
type = "scatter",
mode = "lines",
text = ~Rechnungsgruppe_effort,
hoverinfo = "y+text",
color = ~Difference_inline
)
%>%
layout(legend = invoice_plot_legend,
title = " ",
xaxis = list(title = 'Release date'),
yaxis = list(title = '# of Approved Documents'))
,
plot_ly(data = shared_abs, x = ~Freigabedatum_REAL_YM, y = ~n,
type = "scatter",
mode = "lines",
text = ~Lieferantenname,
hoverinfo = "y+text",
color = ~Lieferantenname_text
)
%>%
layout(legend = vendor_plot_legend,
title = "by vendor absolute delta previous month all documents",
xaxis = list(title = 'Release date'),
yaxis = list(title = '# of Approved Documents w/ & w/o effort')
)
)
)
Thank you so much!

R Leaflet - How to combine text and figure in popup?

I would like to combine text and a figure in a Leaflet Popup. I saw this on a website of Deutsche Bahn: Multi-Object-Popup
Website:
strecken.info
For me it would be sufficient to combine two of these 4 shown "windows" -> One text (paste0()) and one ggplot-figure). Is this possible in R?
Best regards and thank you very much :)
My Code so far:
ll_maps %>%
addCircles(
data = df_temp,
lng = ~x_coord,
lat = ~y_coord,
weight = 1,
radius = 1000,
popup = ~lapply(leafpop::popupGraph(pic_list_temp, width = 500, height = 500), HTML),
label = ~lapply(paste0("<br><b>Textline1</b> = ", tl1_object,
"<br><b>Textline2</b> = ", tl2_object), HTML),
popupOptions = popupOptions(maxWidth = 500),
labelOptions = labelOptions(textsize = "12px"),
opacity = 1,
fillOpacity = 0.5,
color = "red")
Now I would like to combine the label and the popup into one popup so to speak :)

How to use finished GAN model with trianed weights to create new images?

I am following Jeff Heaton's tutorial how to create a GAN with keras. Everything works fine even with my own dataset. However, I cannot figure out how to create a single new images. (Mr. Heaton creates 28 images in form of a collages!)
What I tried without success:
new_fixed_seed = np.random.normal(0, 1, (1, 100))
generated_images = generator.predict(new_fixed_seed)
im = Image.fromarray(generated_images)
Result: TypeError: Cannot handle this data type
What am I doing wrong?
Normally, for me when I calculate generated images I am using the following code for storing them locally:
# combine a squared number of images.
def combine_images(generated_images):
generated_images = np.transpose(generated_images , (0, 3, 1, 2))
num = generated_images.shape[0]
width = int(math.sqrt(num))
height = int(math.ceil(float(num)/width))
shape = generated_images.shape[2:]
image = np.zeros((3,(height+3)*shape[0], (width+3)*shape[1]),
dtype=generated_images.dtype)
for index, img in enumerate(generated_images):
new_shape = (img.shape[0], img.shape[1]+ 4, img.shape[2] + 4)
img_ = np.zeros(new_shape)
img_[:, 2: 2+img.shape[1], 2: 2+img.shape[2]] = img
i = int(index/width)
j = index % width
image[:, i*new_shape[1]: (i+1)*new_shape[1], j*new_shape[2]: (j+1)*new_shape[2]] = img_[:, :, :]
return image
# store combined images
def store_image_maps(images_db, filename):
image = combine_images(images_db)
image = image * 127.5 + 127.5
image = np.swapaxes(image, 0, 1)
image = np.swapaxes(image, 1, 2)
cv2.imwrite(filename,image)
I got it to work but I am not completely satisfied with it as I think it could be cleaner and I think there are unnecessary steps involved:
# SEED_SIZE is 100
fixed_seed = np.random.normal(0, 1, (1, SEED_SIZE))
# used 64x64 because those were my image sizes
image_array = np.full((
64,64, 3),
255, dtype=np.uint8)
generated_images = generator.predict(fixed_seed)
#if you don't use 255 here the images are black
image_array[:] = generated_images * 255
im = Image.fromarray(image_array)
im.save('/content/drive/My Drive/Dataset/test.png')

How to extract input from a dynamic matrix in R shiny

This is related to an old question about creating a matrix-style input in a shiny app with dynamic dimensions. My goal is to have a matrix of numerical inputs (the dimensions of which are determined by other user inputs), and then pass that matrix to other R commands and print some output from those calculations. I have code that successfully executes everything except that I can only access the user inputs as characters.
Here is an example that sets up the input and just prints a couple cells from the matrix (this works fine, but isn't what I need):
shiny::runApp(list(
ui = pageWithSidebar(
headerPanel("test"),
sidebarPanel(
numericInput(inputId = "nrow",
label = "number of rows",
min = 1,
max = 20,
value = 1),
numericInput(inputId = "ncol",
label = "number of columns",
min = 1,
max = 20,
value = 1)
),
mainPanel(
tableOutput("value"),
uiOutput("textoutput"))
),
server = function(input,output){
isolate({
output$value <-renderTable({
num.inputs.col1 <- paste0("<input id='r", 1:input$nrow, "c", 1, "' class='shiny-bound-input' type='number' value='1'>")
df <- data.frame(num.inputs.col1)
if (input$ncol >= 2){
for (i in 2:input$ncol){
num.inputs.coli <- paste0("<input id='r", 1:input$nrow, "c", i, "' class='shiny-bound-input' type='number' value='1'>")
df <- cbind(df,num.inputs.coli)
}
}
colnames(df) <- paste0("time ",as.numeric(1:input$ncol))
df
}, sanitize.text.function = function(x) x)
})
output$textoutput <- renderUI(paste0("Cells [1,1] and [2,2]: ",input$r1c1,",",input$r2c2))
}
))
However, when I try to do any operation on the inputs in the matrix, such as output$textoutput <- renderUI(as.numeric(paste0(input$r1c1))+as.numeric(paste0(input$r2c2))), I get classic R errors like $ operator is invalid for atomic vectors. I have tried many combinations of 'as.numeric', 'as.character', ect. to try to get it into the correct format. When I check the structure of those input cells, I see that they have an extra 'NULL' attribute that I can't seem to get rid of, but I am unsure if that is the root of the problem.
In short, how do I extract the plain numbers from that matrix? Or is there a better way to do this in shiny? The only other solution I'm aware of is the rhandsontable package, which I would prefer not to use if there is a reasonable alternative.
Any suggestions would be very appreciated. Thank you!
Edit/solution: replacing renderUI and uiOutput with renderPrint and verbatimTextOutput solves the problem. Thank you for the comment, blondeclover!

barplot xlim shifts axis -> offset to axis at=midpoints missing

I have the following problem – it is purely an ascetic one but it bothers me that it is not looking nicely:
I generate a simple sideways barplot with ticks at the bottom of the bars. The default setting generates an x-axis which is shorter than my bars (figure 1). To solve this I included xlim. Once I do that the x-axis is slightly shifted to the left so the y-axis is touching the bars (figure 2). This does not look nice at all. I guess xlim somehow overwrite a default parameter but I could not find which. I would be grateful for any suggestions!
rm(list=ls())
data<-c(69,500,597)
names(data)<-c("text1", "text2", "text3")
midpoints<-barplot(data, beside=T, space=1, xlim=c(0,600))
filename=paste("orig.pdf", sep="")
pdf(file=filename, width=10, height =5)
par(mar=c(4,9,1,4))
barplot(data, beside=T, xlab=expression(paste("Text")),
axes=T, cex.lab=2, cex.axis=2, cex.names=2, font.axis = 2,
col=c("grey"), horiz=T, las=1, font.lab=2, space=1,
names.arg=colnames(data))
axis(side = 2, at = midpoints , labels = F, cex.axis=1.5)
dev.off()
filename=paste("with_limit.pdf", sep="")
pdf(file=filename, width=10, height =5)
lim<-c(0,600)
par(mar=c(4,9,1,4))
barplot(data, beside=T, xlab=expression(paste("Text")),
axes=T, cex.lab=2, cex.axis=2, cex.names=2, font.axis = 2,
col=c("grey"), horiz=T, las=1, font.lab=2, space=1,
names.arg=colnames(data), xlim=lim)
axis(side = 2, at = midpoints , labels = F, cex.axis=1.5)
dev.off()
Figure 1
Figure 2
Meanwhile I did find two possible answers both not perfect but working.
The first one is to work with xaxs="r" but for my taste now the offset is too large.
filename=paste("solution1.pdf", sep="")
pdf(file=filename, width=10, height =5)
lim<-c(0,600)
par(mar=c(4,9,1,4))
barplot(data, beside=T, xlab=expression(paste("Text")),
axes=T, cex.lab=2, cex.axis=2, cex.names=2, font.axis = 2,
col=c("grey"), horiz=T, las=1, font.lab=2, space=1,
names.arg=colnames(data), xlim=lim, xaxs="r")
axis(side = 2, at = midpoints , labels = F, cex.axis=1.5)
dev.off()
Solution1
The second option is to have xlim starting in the negative. This has the disadvantage of tuning the offset by hand. In my case I had multiple figures and I wanted it always to be the same so I used (here) 2% of the maximum 600 -> 12. For all others I also used 2% of the maximum. That worked nicely in the end.
filename=paste("solution2.pdf", sep="")
pdf(file=filename, width=10, height =5)
lim<-c(-12,600)
par(mar=c(4,9,1,4))
barplot(data, beside=T, xlab=expression(paste("Text")),
axes=T, cex.lab=2, cex.axis=2, cex.names=2, font.axis = 2,
col=c("grey"), horiz=T, las=1, font.lab=2, space=1,
names.arg=colnames(data), xlim=lim)
axis(side = 2, at = midpoints , labels = F, cex.axis=1.5)
dev.off()
Solution2