Python using custom color in plot - python

I'm having a problem that (I think) should have a fairly simple solution. I'm still a relative novice in Python, so apologies if I'm doing something obviously wrong. I'm just trying to create a simple plot with multiple lines, where each line is colored by its own specific, user-defined color. When I run the following code as a test for one of the colors it ends up giving me a blank plot. What am I missing here? Thank you very much!
import numpy as np
import matplotlib.pyplot as plt
from colour import Color
dbz53 = Color('#DD3044')
*a bunch of arrays of data, two of which are called x and mpt1*
fig, ax = plt.subplots()
ax.plot(x, mpt1, color='dbz53', label='53 dBz')
ax.set_yscale('log')
ax.set_xlabel('Diameter (mm)')
ax.set_ylabel('$N(D) (m^-4)$')
ax.set_title('N(D) vs. D')
#ax.legend(loc='upper right')
plt.show()

The statement
ax.plot(x, mpt1, color='dbz53', label='53 dBz')
is wrong with 'dbz53' where python treated it as a string of unknown rgb value.
You can simply put
color='#DD3044'
and it will work.
Or you can try
color=dbz53.get_hex()
without quote if you want to use the colour module you imported.

In the plot command, you could enter Hex colours. A much more simple way to beautify your plot would be to simply use matplotlib styles. For instance, before any plot function, just write
plt.style.use('ggplot')

Related

How to get colormap plots to fill area?

I'm relatively new to visualization with python. I'm trying to visually show correlation between attributes using a color map, but for some reason the plots aren't filling the entire graph (see pic).
Also, I understand the ticks are bunched (there's 34 attributes), but I wanted to fix the fill issue first. For reference here is the code I have:
correlation = wounds.corr()
fig = plt.figure()
ax = fig.add_subplot(111)
cax = ax.matshow(correlation,cmap='coolwarm', vmin=-1, vmax=1)
fig.colorbar(cax)
ticks = np.arange(0,len(wounds.columns),1)
ax.set_xticks(ticks)
plt.xticks(rotation=90)
ax.set_yticks(ticks)
ax.set_xticklabels(wounds.columns)
ax.set_yticklabels(wounds.columns)
plt.savefig('correlation.jpg')
plt.show()
This is my first time posting here so forgive me if anything is wrong with my question.
Edit: Added code for reference
Best way is to use pandas profiling
Try it out! it would change your life :)
(you can use it directly in your Jupyter notebook):
import pandas_profiling
report = df.profile_report(style={'full_width':True})
If you data is really big you can sample it randomly:
report = df.sample(100000).profile_report(style={'full_width':True})
And you can save it to a file:
report.to_file(output_file="profiling_report.html")

Legend displayed only for a subset of curves in plot

I need to do what has been explained for MATLAB here:
How to show legend for only a specific subset of curves in the plotting?
But using Python instead of MATLAB.
Brief summary of my goal: when plotting for example three curves in the following way
from matplotlib import pyplot as plt
a=[1,2,3]
b=[4,5,6]
c=[7,8,9]
# these are the curves
plt.plot(a)
plt.plot(b)
plt.plot(c)
plt.legend(['a','nothing','c'])
plt.show()
Instead of the word "nothing", I would like not to have anything there.
Using '_' will suppress the legend for a particular entry as following (continue reading for handling underscore _ as a legend). This solution is motivated by the recent post of #ImportanceOfBeingEarnest here.
plt.legend(['a','_','c'])
I would also avoid the way you are putting legends right now because in this way, you have to make sure that the plot commands are in the same order as legend. Rather, put the label in the respective plot commands to avoid errors.
That being said, the straightforward and easiest solution (in my opinion) is to do the following
plt.plot(a, label='a')
plt.plot(b)
plt.plot(c, label='c')
plt.legend()
As #Lucas pointed out in comment, if you want to show an underscore _ as the label for plot b, how would you do it. You can do it using
plt.legend(['a','$\_$','c'])

How to remove extra string "Line2D" in matplotlib legend

I have a string "Line2D" appended in the beginning of my matplotlib legend. How to get rid of it? A simple python script that reproduces this problem is as follows:
import numpy as np
import matplotlib.pylab as plt
x=np.linspace(0,1,20)
y=np.sin(2*x)
z=np.cos(2*x)
p1, = plt.plot(x,y, label='sin(x)')
p2, = plt.plot(x,z, label='cos(x)')
plt.legend([p1, p2])
plt.show()
I get a figure in which I want to get rid of the extra string "Line2D" in the legend. I do not have enough reputation to post images. I was using anaconda python if that matters.
Thanks for your help!
If you pass just one list to legend, it has to be the labels you want to show, not the objects whose labels you want to show. It is converting those line objects to strings, which gives Line2D(...).
Since you gave the lines labels when you created them, you don't need to pass anything to legend. Just plt.legend() will automatically use the labels you provided.
You can use plt.legend(handles=[p1, p2]).

Make more than one chart in same IPython Notebook cell

I have started my IPython Notebook with
ipython notebook --pylab inline
This is my code in one cell
df['korisnika'].plot()
df['osiguranika'].plot()
This is working fine, it will draw two lines, but on the same chart.
I would like to draw each line on a separate chart.
And it would be great if the charts would be next to each other, not one after the other.
I know that I can put the second line in the next cell, and then I would get two charts. But I would like the charts close to each other, because they represent the same logical unit.
You can also call the show() function after each plot.
e.g
plt.plot(a)
plt.show()
plt.plot(b)
plt.show()
Make the multiple axes first and pass them to the Pandas plot function, like:
fig, axs = plt.subplots(1,2)
df['korisnika'].plot(ax=axs[0])
df['osiguranika'].plot(ax=axs[1])
It still gives you 1 figure, but with two different plots next to each other.
Something like this:
import matplotlib.pyplot as plt
... code for plot 1 ...
plt.show()
... code for plot 2...
plt.show()
Note that this will also work if you are using the seaborn package for plotting:
import matplotlib.pyplot as plt
import seaborn as sns
sns.barplot(... code for plot 1 ...) # plot 1
plt.show()
sns.barplot(... code for plot 2 ...) # plot 2
plt.show()
Another way, for variety. Although this is somewhat less flexible than the others. Unfortunately, the graphs appear one above the other, rather than side-by-side, which you did request in your original question. But it is very concise.
df.plot(subplots=True)
If the dataframe has more than the two series, and you only want to plot those two, you'll need to replace df with df[['korisnika','osiguranika']].
I don't know if this is new functionality, but this will plot on separate figures:
df.plot(y='korisnika')
df.plot(y='osiguranika')
while this will plot on the same figure: (just like the code in the op)
df.plot(y=['korisnika','osiguranika'])
I found this question because I was using the former method and wanted them to plot on the same figure, so your question was actually my answer.

weird range value in the colorbar, matplotlib

I am a new user to the python & matplotlib, this might be a simple question but I searched the internet for hours and couldn't find a solution for this.
I am plotting precipitation data from which is in the NetCDF format. What I find weird is that, the data doesn't have any negative values in it.(I checked that many times,just to make sure). But the value in the colorbar starts with a negative value (like -0.0000312 etc). It doesnt make sense because I dont do any manipulations to the data, other that just selecting a part of the data from the big file and plotting it.
So my code doesn't much to it. Here is the code:
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
from netCDF4 import Dataset
cd progs
f=Dataset('V21_GPCP.1979-2009.nc')
lats=f.variables['lat'][:]
lons=f.variables['lon'][:]
prec=f.variables['PREC'][:]
la=lats[31:52]
lo=lons[18:83]
pre=prec[0,31:52,18:83]
m = Basemap(width=06.e6,height=05.e6,projection='gnom',lat_0=15.,lon_0=80.)
x, y = m(*np.meshgrid(lo,la))
m.drawcoastlines()
m.drawmapboundary(fill_color='lightblue')
m.drawparallels(np.arange(-90.,120.,5.),labels=[1,0,0,0])
m.drawmeridians(np.arange(0.,420.,5.),labels=[0,0,0,1])
cs=m.contourf(x,y,pre,50,cmap=plt.cm.jet)
plt.colorbar()
The output that I got for that code was a beautiful plot, with the colorbar starting from the value -0.00001893, and the rest are positive values, and I believe are correct. Its just the minimum value thats bugging me.
I would like to know:
Is there anything wrong in my code? cos I know that the data is right.
Is there a way to manually change the value to 0?
Is it right for the values in the colorbar to change everytime we run the code, cos for the same data, the next time I run the code, the values go like this " -0.00001893, 2.00000000, 4.00000000, 6.00000000 etc"
I want to customize them to "0.0, 2.0, 4.0, 6.0 etc"
Thanks,
Vaishu
Yes, you can manually format everything about the colorbar. See this:
import matplotlib.colors as mc
import matplotlib.pyplot as plt
plt.imshow(X, norm=mc.Normalize(vmin=0))
plt.colorbar(ticks=[0,2,4,6], format='%0.2f')
Many plotting functions including imshow, contourf, and others include a norm argument that takes a Normalize object. You can set the vmin or vmax attributes of that object to adjust the corresponding values of the colorbar.
colorbar takes the ticks and format arguments to adjust which ticks to display and how to display them.

Categories

Resources