Bar with different color - python

I am working with matplotlib and below you can see my data and my plot.
data = {
'type_sale': ['g_1','g_2','g_3','g_4','g_5','g_6','g_7','g_8','g_9','g_10'],
'open':[70,20,24,150,80,90,60,90,20,20],
}
df = pd.DataFrame(data, columns = ['type_sale',
'open',
])
df.plot(x='type_sale', kind='bar', title='Bar Graph')
So now I want to put a different color (color = 'red') on the fourth bar. I tryed but I colored all instead only one.
So can anybody help me how to solve this ?

The ax.bar() method returns a list of bars that you can then manipulate, in your case with .set_color():
import matplotlib.pyplot as plt
f=plt.figure()
ax=f.add_subplot(1,1,1)
## bar() will return a list of bars
barlist = ax.bar([1,2,3,4], [1,2,3,4])
barlist[3].set_color('r')
plt.show()

You can try this solution
# libraries
import numpy as np
import matplotlib.pyplot as plt
# create a dataset
height = [3, 12, 5, 18, 45]
bars = ('A', 'B', 'C', 'D', 'E')
x_pos = np.arange(len(bars))
# Create bars with different colors
plt.bar(x_pos, height, color=['black', 'red', 'green', 'blue', 'cyan'])
# Create names on the x-axis
plt.xticks(x_pos, bars)
# Show graph
plt.show()
Here is the documentation link
Link

Related

Put the values in the middle of the bars in histogram plot [duplicate]

This question already has answers here:
How to display custom values on a bar plot
(8 answers)
Display count on top of seaborn barplot [duplicate]
(4 answers)
How to add vertically centered labels in bar chart matplotlib [duplicate]
(1 answer)
Closed 7 days ago.
I have a histogram plot and I want to add the values of the VAL in the middle of the bar plot with a color which are fitted with the color of the bar. Thank you. Like the following image I only use the black color to show the number
import numpy as np
import seaborn as sns
VAL = [8, 4, 5, 20]
objects = ['h', 'b', 'c', 'a']
y_pos = np.arange(len(objects))
cmap = plt.get_cmap('RdYlGn_r')
norm = plt.Normalize(vmin=min(VAL), vmax=max(VAL))
ax = sns.barplot(x=VAL, y=objects, hue=VAL, palette='RdYlGn_r', dodge=False)
plt.yticks(y_pos, objects)
plt.show()
You just have to add the Axis.text() method before showing the plot to add the text on the chart.
Given below the code will help you to understand the method more properly:
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
VAL = [8, 4, 5, 20]
objects = ['h', 'b', 'c', 'a']
y_pos = np.arange(len(objects))
cmap = plt.get_cmap('RdYlGn_r')
norm = plt.Normalize(vmin=min(VAL), vmax=max(VAL))
ax = sns.barplot(x=VAL, y=objects, hue=VAL, palette='RdYlGn_r', dodge=False)
for i, v in enumerate(VAL):
ax.text(v/2, i, str(v),
color = 'blue', fontweight = 'bold')
plt.yticks(y_pos, objects)
plt.show()
You can styling the font as well can give the color to the font
Hope it will help you to get the result
With regards to adding the value to the middle of the barplot, you can accomplish it with the text function:
for i, v in enumerate(VAL):
ax.text(v/2, i, str(v))
As for coloring the text with the same color as the bar, I think you wouldn't be able to see the text.

Assign color of mean markers while using seaborn hue

In Seaborn, I can assign the color of mean marker by providing meanprops
e.g. :
meanprops: {'marker': 'o', 'markeredgecolor': c,
'markerfacecolor': 'none', 'markersize': 4}
However, if I make a plot using hue, this will set same colour of mean to all the categories. How can i also apply hue color to mean also.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
df_merge = pd.DataFrame(data={'AOD_440nm': np.random.rand(20),
'month': np.tile(['Jan','Feb'], 10),
'kind': np.repeat(['A', 'B'], 10)})
fig,ax = plt.subplots()
sns.boxplot(x='month', y='AOD_440nm', hue='kind', data=df_merge,
showfliers=False, whis=[5, 95],
palette=sns.color_palette(('r', 'k')),
showmeans=True)
for i, artist in enumerate(ax.artists):
# Set the linecolor on the artist to the facecolor, and set the facecolor to None
col = artist.get_facecolor()
artist.set_edgecolor(col)
artist.set_facecolor('None')
In short, how can I change colour of means?
You could loop through all the "lines" generated by the boxplot. The boxplot generates multiple lines per box, one for each element. The marker for the mean is also a "line", but with linestyle None, only having a marker (similar to how plt.plot can draw markers). The exact amount of lines per box depends on the options (as in: with/without mean, whiskers, ...). As changing the marker color of the non-marker lines doesn't have visible effect, changing all marker colors is the easiest approach.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
df_merge = pd.DataFrame(data={'AOD_440nm': np.random.rand(20),
'month': np.tile(['Jan', 'Feb'], 10),
'kind': np.repeat(['A', 'B'], 10)})
fig, ax = plt.subplots()
sns.boxplot(x='month', y='AOD_440nm', hue='kind', data=df_merge,
showfliers=False, whis=[5, 95],
palette=sns.color_palette(('r', 'k')),
showmeans=True)
num_artists = len(ax.artists)
num_lines = len(ax.lines)
lines_per_artist = num_lines // num_artists
for i, artist in enumerate(ax.artists):
# Set the linecolor on the artist to the facecolor, and set the facecolor to None
col = artist.get_facecolor()
artist.set_edgecolor(col)
artist.set_facecolor('None')
# set the marker colors of the corresponding "lines" to the same color
for j in range(lines_per_artist):
ax.lines[i * lines_per_artist + j].set_markerfacecolor(col)
ax.lines[i * lines_per_artist + j].set_markeredgecolor(col)
plt.show()
PS: An alternative to artist.set_facecolor('None') could be to use a strong transparency: artist.set_alpha(0.1).

Seaborn violin plots don't align with x-axis labels

I am attempting to build a violin plot to illustrate depth on the y-axis and a distance away from a known point on the x-axis. I am able to get the x-axis labels to distribute appropriately spaced on the x-axis based on the variable distances but i am unable to get the violin plots to align. They plots appear to be shifted to the y-axis. Any help would be appreciated. My code is below:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
path = 'O:\info1.csv'
df = pd.read_csv(path)
item = ['a', 'b', 'c', 'd', 'e', 'f']
dist = [450, 1400, 2620, 3100, 3830, 4940]
plt.rcParams.update({'font.size': 15})
fig, axes1 = plt.subplots(figsize=(20,10))
axes1 = sns.violinplot(x='item', y='surface', data=df, hue = 'item', order = (item))
axes1.invert_yaxis()
axes1.set_xlabel('Item')
axes1.set_ylabel('Depth')
axes1.set_xticks(dist)
plt.xticks(rotation=20)
plt.show()
Example dataset:
You cannot use seaborn violin plot, because from the vignette:
This function always treats one of the variables as categorical and
draws data at ordinal positions (0, 1, … n) on the relevant axis, even
when the data has a numeric or date type.
So if you draw it directly with seaborn, it is categorical:
sns.violinplot(x='dist', y='surface', data=df, hue = 'item',dodge=False,cut=0)
To place the boxplot according, you need to use matplotlib, first we get the data out in the format required and define a color palette:
surface_values = list([np.array(value) for name,value in df.groupby('item')['surface']])
dist_values = df.groupby('item')['dist'].agg("mean")
pal = ["crimson","darkblue","rebeccapurple"]
You need to set the width, provide the distance, and for the inner "box", we modify the code from here:
fig, ax = plt.subplots(1, 1,figsize=(8,4))
parts = ax.violinplot(surface_values,widths=200,positions=dist_values,
showmeans=False, showmedians=False,showextrema=False)
for i,pc in enumerate(parts['bodies']):
pc.set_facecolor(pal[i])
pc.set_edgecolor('black')
pc.set_alpha(1)
quartile1, medians, quartile3 = np.percentile(surface_values, [25, 50, 75], axis=1)
whiskers = np.array([
adjacent_values(sorted_array, q1, q3)
for sorted_array, q1, q3 in zip(surface_values, quartile1, quartile3)])
whiskersMin, whiskersMax = whiskers[:, 0], whiskers[:, 1]
inds = dist_values
ax.scatter(inds, medians, marker='o', color='white', s=30, zorder=3)
ax.vlines(inds, quartile1, quartile3, color='k', linestyle='-', lw=5)
ax.vlines(inds, whiskersMin, whiskersMax, color='k', linestyle='-', lw=1)
If you don't need the inner box, you can just call plt.violin ...
thanks for including a bit of data.
To change your plot, the item and dist variables in your code need to be adjusted, and remove the item = [a,b...] and dist = [] arrays in your code. The ticks on the x-axis using the axes1.set_xticks needs a bit of tweaking to get what you're looking for there.
Example 1:
removed the two arrays that were creating the plot you were seeing before; violinplot function unchanged.
# item = ['a', 'b', 'c', 'd', 'e', 'f'] * Removed
# dist = [450, 1400, 2620, 3100, 3830, 4940] * Removed
plt.rcParams.update({'font.size': 15})
fig, axes1 = plt.subplots(figsize=(20,10))
axes1 = sb.violinplot(x='item', y='surface', data=df, hue = 'item', inner = 'box')
axes1.invert_yaxis()
axes1.set_xlabel('Item')
axes1.set_ylabel('Depth')
#axes1.set_xticks(dist) * Removed
plt.xticks(rotation=20)
plt.show()
Inside each curve, there is a black shape with a white dot inside. This is the miniature box plot mentioned above. If you'd like to remove the box plot, you can set the inner = None parameter in the violinplot call to simplify the look of the final visualization.
Example 2:
put dist on your x axis in place of the xticks.
plt.rcParams.update({'font.size': 15})
plt.subplots(figsize=(20,10))
# Put 'dist' as your x input, keep your categorical variable (hue) equal to 'item'
axes1 = sb.violinplot(data = df, x = 'dist', y = 'surface', hue = 'item', inner = 'box');
axes1.invert_yaxis()
axes1.set_xlabel('Item')
axes1.set_ylabel('Depth');
I'm not confident the items and the distances you are working with have a relationship you want to show on the x-axis, or if you just want to use those integers as your tick marks for that axis. If there is an important relationship between the item and the dist, you could use a dictionary new_dict = {450: 'a', 1400: 'b', 2620: 'c' ...
Hope you find this helpful.

Can't set different colors for each bar when I put it on top of a clustergram

Here is my example, I can't get different bar colors defined.... for some reason all are red.
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# initiliaze a dataframe with index and column names
idf = pd.DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6]), ('C', 10,
20, 30]), ('D', [14, 15, 16])], orient='index', columns=['x', > 'y', 'z'])
# Plot the clustermap which will be a figure by itself
cax = sns.clustermap(idf, col_cluster=False, row_cluster=True)
# Get the column dendrogram axis
cax_col_dend_ax = cax.ax_col_dendrogram.axes
# Plot the boxplot on the column dendrogram axis
idf.iloc[0,:].plot(kind='bar', ax=cax_col_dend_ax, color = ['r', 'g', 'b'])
# Show the plot
plt.show()
Your code works fine for me. It seems you are using old python version because I got a FutureWarning: from_items is deprecated.. Although this is from pandas but you might want to upgrade. Nevertheless, you can still change the colors as follows
import matplotlib as mpl
# Your code here
ax1 = idf.iloc[0,:].plot.bar(ax=cax_col_dend_ax)
colors = ['r', 'g', 'b']
bars = [r for r in ax1.get_children() if isinstance(r, mpl.patches.Rectangle)]
for i, bar in enumerate(bars[0:3]):
bar.set_color(colors[i])

How to use a colorscale palette with plotly and python?

I am trying to change the colors of a stack bar chart that I draw in python with plotly and cufflinks (cufflinks library allows to draw chart directly form a dataframe which is super useful).
Let's take the following figure (I use jupyter notebook):
import plotly.plotly as py
import cufflinks as cf
cf.set_config_file(offline=True, world_readable=True, theme='white')
df = pd.DataFrame(np.random.rand(10, 4), columns=['A', 'B', 'C', 'D'])
df.iplot(kind='bar', barmode='stack')
How do you implement a new color palette using the above code? I would like to use the 'Viridis' color palette. I haven't found a way to modify the colors of the graph or to use a color palette to automatically color differently the different stack of the bar chart. Does one of you knows how to do it?
Many thanks for your help,
trace0 = go.Scatter(
x = foo,
y = bar,
name = 'baz',
line = dict(
color = ('rgb(6, 12, 24)'),
width = 4)
)
This allows you to change the color of the line or you could use
colors = `['rgb(67,67,67)', 'rgb(115,115,115)', 'rgb(49,130,189)', 'rgb(189,189,189)']`
for separate lines of a graph. To use the specified color gradient try
data = [
go.Scatter(
y=[1, 1, 1, 1, 1],
marker=dict(
size=12,
cmax=4,
cmin=0,
color=[0, 1, 2, 3, 4],
colorbar=dict(
title='Colorbar'
),
colorscale='Viridis'
),
mode='markers')
]
Found an answer to my problem:
import plotly.plotly as py
import cufflinks as cf
from bokeh.palettes import viridis
cf.set_config_file(offline=True, world_readable=True, theme='white')
colors = viridis(4)
df = pd.DataFrame(np.random.rand(10, 4), columns=['A', 'B', 'C', 'D'])
fig = df.iplot(kind='bar', barmode='stack',asFigure = True)
for i,color in enumerate(colors):
fig['data'][i]['marker'].update({'color': color})
fig['data'][i]['marker']['line'].update({'color': color})
py.offline.iplot(fig)
To build upon the answer of #Peslier53:
You can specify colors or a colorscale directly within df.iplot():
import plotly.plotly as py
import cufflinks as cf
from bokeh.palettes import viridis
cf.set_config_file(offline=True, world_readable=True, theme='white')
colors = viridis(4)
df = pd.DataFrame(np.random.rand(10, 4), columns=['A', 'B', 'C', 'D'])
df.iplot(kind='bar', barmode='stack', colors = colors)
This saves you some lines of code and makes plotting very convenient.
It also works with any list of colors (depending on the graph type, heat maps need a color gradient instead of a color list for example), so you can also use custom colors.

Categories