How to get different colors in different columns using stack bar in python - bar-chart

Question :- How to get Alternate colors in different stacked bar using Matplotlib or Seaborn.
Say for Example - I have 3 stacked bars in a plot.
First bar should have say green, blue, yellow
Second stack bar should have orange, blue, red
Third stack bar should have blue, purple, red.
I have written the below code, it gives me the stack bar, but not the color combination as i explained above. I am getting all the 3 stack bars with same kind of colors which i don't need.
Any help..
TESTING PLOT 3
import numpy as np
from matplotlib import pyplot as plt
num_set = [{'USA':914, 'GBR':70, 'IND':48},
{'USA':770, 'GBR':67, 'IND':16},
{'USA':282, 'GBR':20, 'IND':12}]
lan_guage = [['USA','GBR','IND'],
['GBR','IND','USA'],
['IND','USA','GBR']]
colors = ["r","g","b"]
names = sorted(num_set[0].keys())
values = np.array([[data[name] for name in order] for data,order in zip(num_set, lan_guage)])
lefts = np.insert(np.cumsum(values, axis=1),0,0, axis=1)[:, :-1]
orders = np.array(lan_guage)
bottoms = np.arange(len(lan_guage))
for name, color in zip(names, colors):
idx = np.where(orders == name)
value = values[idx]
left = lefts[idx]
plt.bar(left, height=0.8, width=value, bottom=bottoms,
color=color, orientation="horizontal", label=name)
plt.yticks(bottoms+0.4, ["Student-%d" % (t+1) for t in bottoms])
plt.legend(loc="best", bbox_to_anchor=(1.0, 1.00))
plt.subplots_adjust(right=0.75)
# Turn on the grid
plt.minorticks_on()
plt.grid(which='major', linestyle='-', linewidth='0.5', color='green')
plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black')
plt.show()

N = 3 # No of Countries
top_sector = (914,300, 200) ## No of Investment in top sectors for C1/C2/C3
second_sector = (770,200,100) ## No of Investment in 2nd highest sector for C1/C2/C3
third_sector = (282,100,50) ## No of Investment in 3rd highest sector for C1/C2/C3
ind = np.arange(N)
width = 0.35
## p1 thru p5 are for 5 sectors.
p1 = plt.bar(ind,top_sector,width,color=['green','grey','green'])
p2 = plt.bar(ind,second_sector,width,color=['grey','green','purple'])
p3 = plt.bar(ind,third_sector,width,color=['red','brown','brown'])
p4 = plt.bar(ind,fourth_sector,width,color=['brown'])
p5 = plt.bar(ind,fifth_sector,width,color=['purple'])
plt.xlabel('Top 3 Countries for Investment')
plt.ylabel('No of Investment (Count)')
plt.title('No of Investment in top 3 sectors of top 3 countries')
plt.xticks(ind,('USA' , 'GBR', 'IND'))
plt.yticks(np.arange(0,1000,200))
plt.legend((p1[0],p2[0],p3[0],p4[0],p5[0]),('Others',' Health', 'Entertainment', 'Cleantech / Semiconductors','News,Searching/Msg'))
plt.show()[enter image description here][1]
IMAGE :-
[1]: https://i.stack.imgur.com/A9fsI.png

Related

Niftis being plotted skewed

When I plot single images they appear to be skewed, but doesn't appear that way when I look at the images in 3DSlicer or another viewer. I'm not sure if there's something I should be adjusting that I'm not aware of. The below is how I converted from DICOM:
dicom2nifti.convert_directory(path_to_dicom_before, path_to_dicom_before_converted, compression=True, reorient=True)
dicom2nifti.convert_directory(path_to_dicom_post, path_to_dicom_post_converted, compression=True, reorient=True)
print(glob(path_to_dicom_before_converted + '*.nii.gz'))
nii_before = nib.load(glob(path_to_dicom_before_converted + '*.nii.gz')[0])
nii_after = nib.load(glob(path_to_dicom_post_converted + '*.nii.gz')[0])
nii_before_data = nii_before.get_fdata()
nii_after_data = nii_after.get_fdata()
fig, ax = plt.subplots(figsize=[10, 5])
plotting.plot_img(nii_before, cmap='gray', axes=ax)
plt.show()
fig, ax = plt.subplots(figsize=[10, 5])
plotting.plot_img(nii_after, cmap='gray', axes=ax)
plt.show()
plt.imshow(nii_before_data[100], cmap='bone')
plt.axis('off')
plt.show()
Affine of the first:
[[-3.19454312e-01 7.17869774e-02 3.95075195e-02 6.01478424e+01]
[ 5.83867840e-02 2.97792435e-01 -2.28872180e-01 1.27874863e+02]
[ 4.69673797e-02 1.18071720e-01 5.53225577e-01 1.12181287e+03]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00]]
As you can see in this answer you are plotting the row 100 with all columns and all slices! Also you need to plot the pixel array nii_before_data and not the whole Nifti image nii_before which contains other types of data.
you can try:
nii_before = nib.load(glob(path_to_dicom_before_converted + '*.nii.gz')[0])
nii_after = nib.load(glob(path_to_dicom_post_converted + '*.nii.gz')[0])
nii_before_data = nii_before.get_fdata()
nii_after_data = nii_after.get_fdata()
## Same goes for nii_after_data
if(len(nii_before_data.shape)==3):
for slice_Number in range(nii_before_data.shape[2]):
plt.imshow(nii_before_data[:,:,slice_Number ])
plt.show()
if(len(nii_before_data.shape)==4):
for frame in range(nii_before_data.shape[3]):
for slice_Number in range(nii_before_data.shape[2]):
plt.imshow(nii_before_data[:,:,slice_Number,frame])
plt.show()
If you can provide a sample Nifti Image the solution might be more precise according to your data.

Plotly Express: Prevent bars from stacking when Y-axis catgories have the same name

I'm new to plotly.
Working with:
Ubuntu 20.04
Python 3.8.10
plotly==5.10.0
I'm doing a comparative graph using a horizontal bar chart. Different instruments measuring the same chemical compounds. I want to be able to do an at-a-glance, head-to-head comparison if the measured value amongst all machines.
The problem is; if the compound has the same name amongst the different instruments - Plotly stacks the data bars into a single bar with segment markers. I very much want each bar to appear individually. Is there a way to prevent Plotly Express from automatically stacking the common bars??
Examples:
CODE
gobardata = []
for blended_name in _df[:20].blended_name: # should always be unique
##################################
# Unaltered compound names
compound_names = [str(c) for c in _df[_df.blended_name == blended_name]["injcompound_name"].tolist()]
# Random number added to end of compound_names to make every string unique
# compound_names = ["{} ({})".format(str(c),random.randint(0, 1000)) for c in _df[_df.blended_name == blended_name]["injcompound_name"].tolist()]
##################################
deltas = _df[_df.blended_name == blended_name]["delta_rettime"].to_list()
gobardata.append(
go.Bar(
name = blended_name,
x = deltas,
y = compound_names,
orientation='h',
))
fig = go.Figure(data = gobardata)
fig.update_traces(width=1)
fig.update_layout(
bargap=1,
bargroupgap=.1,
xaxis_title="Delta Retention Time (Expected - actual)",
yaxis_title="Instrument name(Injection ID)"
)
fig.show()
What I'm getting (Using actual, but repeated, compound names)
What I want (Adding random text to each compound name to make it unique)
OK. Figured it out. This is probably pretty klugy, but it consistently works.
Basically...
Use go.FigureWidget...
...with make_subplots having a common x-axis...
...controlling the height of each subplot based on number of bars.
Every bar in each subplot is added as an individual trace...
...using a dictionary matching bar name to a common color.
The y-axis labels for each subplot is a list containing the machine name as [0], and then blank placeholders ('') so the length of the y-axis list matches the number of bars.
And manually manipulating the legend so each bar name appears only once.
# Get lists of total data
all_compounds = list(_df.injcompound_name.unique())
blended_names = list(_df.blended_name.unique())
#################################################################
# The heights of each subplot have to be set when fig is created.
# fig has to be created before adding traces.
# So, create a list of dfs, and use these to calculate the subplot heights
dfs = []
subplot_height_multiplier = 20
subplot_heights = []
for blended_name in blended_names:
df = _df[(_df.blended_name == blended_name)]#[["delta_rettime", "injcompound_name"]]
dfs.append(df)
subplot_heights.append(df.shape[0] * subplot_height_multiplier)
chart_height = sum(subplot_heights) # Prep for the height of the overall chart.
chart_width = 1000
# Make the figure
fig = make_subplots(
rows=len(blended_names),
cols=1,
row_heights = subplot_heights,
shared_xaxes=True,
)
# Create the color dictionary to match a color to each compound
_CSS_color = CSS_chart_color_list()
colors = {}
for compound in all_compounds:
try: colors[compound] = _CSS_color.pop()
except IndexError:
# Probably ran out of colors, so just reuse
_CSS_color = CSS_color.copy()
colors[compound] = _CSS_color.pop()
rowcount = 1
for df in dfs:
# Add bars individually to each subplot
bars = []
for label, labeldf in df.groupby('injcompound_name'):
fig.add_trace(
go.Bar(x = labeldf.delta_rettime,
y = [labeldf.blended_name.iloc[0]]+[""]*(len(labeldf.delta_rettime)-1),
name = label,
marker = {'color': colors[label]},
orientation = 'h',
),
row=rowcount,
col=1,
)
rowcount += 1
# Set figure to FigureWidget
fig = go.FigureWidget(fig)
# Adding individual traces creates redundancies in the legend.
# This removes redundancies from the legend
names = set()
fig.for_each_trace(
lambda trace:
trace.update(showlegend=False)
if (trace.name in names) else names.add(trace.name))
fig.update_layout(
height=chart_height,
width=chart_width,
title_text="∆ of observed RT to expected RT",
showlegend = True,
)
fig.show()

Colored Bar Graph According to its Value - GNU Octave

I want to set the color of the bar graph according to its value. Here is the data
Kp index
UT
0
76.00
2
76.12
5
76.25
6
76.37
5
76.50
8
76.62
8
76.75
7
76.87
8
77.00
This is what I wan to replicate:
**0-3 = green;
4 = yellow;
5-9 = red**
I tried for loop but it was not successful.
Thank you for your help.
You can draw your bar graph one bar at a time, so that you can have full control of each bar as a separate graphics object:
x = 1:10;
y = randi( 10, [1,10] );
colours = { 'g', 'g', 'g', 'g', 'y', 'r', 'r', 'r', 'r', 'r' };
hold on
for i = 1 : length(x)
H(i) = bar( x(i), y(i), 0.4, 'facecolor', colours{i} );
endfor
hold off;
PS. Alternatively, if you don't want that much fine-grained control, and you know that a group will always have the same colour, then you can draw each 'group' separately, instead of each bar separately, and simply set a single colour for the whole group.

Straight line appearing in seaboard barplot

I have a line appearing on one line of my bar plot
this is what it looks like
and my code below
sns.barplot(x='Police force sent NRM referral for Crime Recording', y='Total', data=dfForces1)
sns.despine()
plt. xticks(rotation=90)
import matplotlib.ticker as ticker
ax_data = sns.barplot(x= 'Police force sent NRM referral for Crime Recording', y = 'Total', data=dfForces1) # change as per how you are plotting, just for an example
ax_data.yaxis.set_major_locator(ticker.MultipleLocator(40)) # it would have a tick frequency of 40, change 40 to the tick-frequency you want.
ax_data.yaxis.set_major_formatter(ticker.ScalarFormatter())````

Number of observations when using plm with first differences

I have a simple issue after running a regression with panel data using plm with a dataset that resembles the one below:
dataset <- data.frame(id = rep(c(1,2,3,4,5), 2),
time = rep(c(0,1), each = 5),
group = rep(c(0,1,0,0,1), 2),
Y = runif(10,0,1))
model <-plm(Y ~ time*group, method = 'fd', effect = 'twoways', data = dataset,
index = c('id', 'time'))
summary(model)
stargazer(model)
As you can see, both the model summary and the table displayed by stargazer would say that my number of observations is 10. However, is it not more correct to say that N = 5, since I have taken away the time element after with the first differences?
You are right about the number of observations. However, your code does not what you want it to do (a first differenced model).
If you want a first differenced model, switch the argument method to model (and delete argument effect because it does not make sense for a first differenced model):
model <-plm(Y ~ time*group, model = 'fd', data = dataset,
index = c('id', 'time'))
summary(model)
## Oneway (individual) effect First-Difference Model
##
## Call:
## plm(formula = Y ~ time * group, data = dataset, model = "fd",
## index = c("id", "time"))
##
## Balanced Panel: n = 5, T = 2, N = 10
## Observations used in estimation: 5
##
## Residuals:
## Min. 1st Qu. Median 3rd Qu. Max.
## -0.3067240 -0.0012185 0.0012185 0.1367080 0.1700160
## [...]
In the summary output, you can see the number of observations in your original data (N=10) and the number of observations used in the FD model (5).