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

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

Related

Some bars are missing from the plotly dash plot randomly

I am creating a dashboard using Plotly Dash which contains plots with a bar and a line graph on the common x axis. The code is working fine when I run it, however when I am selecting different options from the dropdown to change the graph, some bars go missing from the plot randomly for some options.
Here is an example that’s working perfectly fine.perfectly fine image
And here is an example where a bar goes missing from the plot when i select a different option from dropdown.
image with missing bar
I am not sure what’s wrong. I have checked if the data is missing for the missing bar but it’s there and when I am hovering over the missing bar area in the plot, it is also showing me the value there but not the bar. For reference, here is my code…
trace1 = go.Scatter(
mode='lines+markers+text',
x = df1['Date'],
y = df1['AVG'],
name="Avg time(mins)",
text=df1['AVG'],
textposition='bottom right',
textfont_color='black',
marker_color='blue',
opacity=1
)
trace2 = go.Bar(
x = df1['Date'],
y = df1['Id_Count'],
name="Count",
ids=df1['Id_Count'],
text=df1['Id_Count'],
textposition='inside',
insidetextfont_color='#45FC03',
hoverinfo='x+y',
yaxis='y2',
marker_color ='#180702',
marker_line_width=1.5,
marker_line_color='black',
opacity=0.72
)
data1 = [trace1, trace2]
layout1 = go.Layout(
title_text='Day wise stats',
title_font_color='#45FC03',
width=1300,
height=400,
yaxis=dict(
side = 'right'
),
yaxis2=dict(
overlaying='y',
anchor='y3',
)
)
fig1 = go.Figure(data=data1, layout=layout1)
fig1.update_layout(template='plotly_dark',
plot_bgcolor='#F0E199', paper_bgcolor='#282522', margin_l=50, margin_t=80, margin_b=60)
fig1.update_xaxes(showgrid=False, zeroline=False)
fig1.update_yaxes(showgrid=False, zeroline=False)
Please, any help would be appreciated for a solution to this problem.
contents of bars is based on data in dataframe
below code shows bar disappears if underlying dataframe has NaN as value
import pandas as pd
import numpy as np
import plotly.graph_objects as go
df1 = pd.DataFrame({"Date":pd.date_range("28-sep-2021", freq="D", periods=7), "AVG":np.round(np.random.uniform(2,5,7),2), "Id_Count":np.random.randint(2000,3000,7)})
def graph(df1):
trace1 = go.Scatter(
mode='lines+markers+text',
x = df1['Date'],
y = df1['AVG'],
name="Avg time(mins)",
text=df1['AVG'],
textposition='bottom right',
textfont_color='black',
marker_color='blue',
opacity=1
)
trace2 = go.Bar(
x = df1['Date'],
y = df1['Id_Count'],
name="Count",
ids=df1['Id_Count'],
text=df1['Id_Count'],
textposition='inside',
insidetextfont_color='#45FC03',
hoverinfo='x+y',
yaxis='y2',
marker_color ='#180702',
marker_line_width=1.5,
marker_line_color='black',
opacity=0.72
)
data1 = [trace1, trace2]
layout1 = go.Layout(
title_text='Day wise stats',
title_font_color='#45FC03',
width=800,
height=400,
yaxis=dict(
side = 'right'
),
yaxis2=dict(
overlaying='y',
anchor='y3',
)
)
fig1 = go.Figure(data=data1, layout=layout1)
fig1.update_layout(template='plotly_dark',
plot_bgcolor='#F0E199', paper_bgcolor='#282522', margin_l=50, margin_t=80, margin_b=60)
fig1.update_xaxes(showgrid=False, zeroline=False)
fig1.update_yaxes(showgrid=False, zeroline=False)
return fig1
graph(df1).show()
df1.loc[df1.sample(1).index, "Id_Count"] = np.nan
graph(df1).show()

How to effectively adjust graph margin or padding in dash plotly

I have plotted two graphs using plotly dash. But when the y-axis / x-axis tick size is more it gets cut off.
Y-axis :
Code :
data = [go.Scatter(x = df[df['S2PName-Category']==category]['S2BillDate'],
y = df[df['S2PName-Category']==category]['totSale'],
mode = 'markers+lines',
name = category) for category in df['S2PName-Category'].unique()]
layout = go.Layout(title='Category Trend',
xaxis = dict(title = 'Time Frame', tickformat = '%d-%b-%y'),
yaxis = dict(tickprefix= '₹', tickformat=',.2f',type='log'),
hovermode = 'closest',
plot_bgcolor = colors['background'],
paper_bgcolor = colors['background'],
font = dict(color = colors['text'])
)
X-Axis :
Code :
data = [go.Scatter(x = df[df['S2PName']==item]['S2BillDate'],
y = df[df['S2PName']==item]['totSale'],
mode = 'markers+lines',
name = item) for item in items]
layout = go.Layout(title='Category Trend',
xaxis = dict(title = 'Time Frame' , tickformat = '%d-%b'),
yaxis = dict(tickprefix= '₹', tickformat=',.2f',type='log',autorange = True),
hovermode = 'closest',
plot_bgcolor = colors['background'],
paper_bgcolor = colors['background'],
font = dict(color = colors['text'])
)
In the above 2 graphs , as the length of the tick value increases, it gets cut off . Is there a better way to handle this ?
Credit for #Flavia Giammarino in comments for the reference to the docs. I'm posting the answer for completeness.
https://plotly.com/python/setting-graph-size/
From that link the example below shows how to set margin:
fig.update_layout(
margin=dict(l=20, r=20, t=20, b=20),
)
Where l r t b correspond to left, right, top, bottom.
I had a similar problem with some Dash/Plotly charts and long y axis labels being truncated or hidden. There didn't seem to be much information or documentation on this issue, so it took a while to solve.
Solution: add this code to the layout settings to prevent truncation of the y axes labels:
fig.update_layout(
yaxis=dict(
automargin=True
)
)
or you can update the yaxes setting specifically:
fig.update_yaxes(automargin=True)
Update: I tried another version of Plotly (5.10 or above) which mentions setting the automargin setting to any combination of automargin=['left+top+right+bottom'] with similar results. This still seems a bit unstable and doesn't solve all possible scenarios or corner cases, but works fine in most cases, especially when the browser window is maximized.

A way to scroll a layout's widgets using mouse?

Can you help me on how to scroll a layout's content using mouse? Or is it possible?
I created this notification-center widget and I used wibox.layout.fixed.vertical() to act the storage of the widgets/notifications. My problem is having too many widgets will consume all the space and there will be no enough space to display the other widgets. So I've been trying to make the widget inside the wibox.layout.fixed.vertical() scrollable but I'm always reaching a dead end. I also tried the wibox.container.scroll but as the documentation says:
Please note that mouse events do not propagate to widgets inside of the scroll container.
This is the simple code I'm using:
-- Layout
local notifbox_layout = wibox.layout.fixed.vertical()
-- Add these textbox widgets to layout
-- Make this widgets scrollable if there's too many of them
notifbox_layout:insert(1, wibox.widget.textbox('String 1'))
notifbox_layout:insert(1, wibox.widget.textbox('String 2'))
notifbox_layout:insert(1, wibox.widget.textbox('String 3'))
notifbox_layout:insert(1, wibox.widget.textbox('String 4'))
notifbox_layout:insert(1, wibox.widget.textbox('String 5'))
-- Mouse event
notifbox_layout:buttons(
gears.table.join(
awful.button(
{},
4,
nil,
function()
-- some magic here to scroll up
end
),
awful.button(
{},
5,
nil,
function()
-- some magic here to scroll down
end
)
)
)
This is the notification center with no enough space to show the other widgets
Sorry if I explained this bad. I'm not really that good in english.
Nevermind. I tried Uli Schlachter's answer here. And it works perfectly. I modified it a bit and then it looks like this.
local w = wibox{ x = 100, y = 100, width = 100, height = 20, visible = true }
my_wiget = function()
return some_widget
end
local own_widget = wibox.widget.base.make_widget()
local offset_x, offset_y = -20, 0
function own_widget:layout(context, width, height)
-- No idea how to pick good widths and heights for the inner widget.
return { wibox.widget.base.place_widget_at(my_widget(), offset_x, offset_y, 200, 40) }
end
own_widget:buttons(
awful.util.table.join(
awful.button(
{},
4,
function()
if offset_y <= 490 then
offset_y = offset_y + 5
end
own_widget:emit_signal("widget::layout_changed")
end
),
awful.button(
{},
5,
function()
if offset_y >= 5 then
offset_y = offset_y - 5
end
own_widget:emit_signal("widget::layout_changed")
end
)
)
)
w:set_widget(own_widget)

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')

Plot colours in HTML differ from within RStudio after knit

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.