Print weighted color palette in matplotlib - matplotlib

I understand that one can print a color palette (equally weighted) with the following code:
import matplotlib.pyplot as plt
blue_red = [(0,0,255), (255, 0,0)] # or any other list of RGB tuples
plt.imshow([blue_red])
However, how could I show weighted palettes? For example if I wanted to weight 90% blue and 10% red instead of 50-50?

You can do it like this:
import matplotlib.pyplot as plt
blue = (0,0,255)
red = (255, 0,0)
weight1 = 9
weight2 = 1
blue_red = [blue for _ in range (weight1)] + [red for _ in range(weight2)]
plt.imshow([blue_red])
plt.show()
or simply:
plt.imshow([[(0,0,255) for _ in range(9)] + [(255, 0,0) for _ in range(1)]])
You can also add an extent argument to clean up your corrdinates:
plt.imshow([[(0,0,255) for _ in range(9)] + [(255, 0,0) for _ in range(1)]],extent=[0,10,0,1])

Related

centre the peak at x=0

Right now the rectangle signal is centre on x = 4, how can I make it centre on x = 0
def rect(n,T):
a = np.zeros(int((n-T)/2,))
b = np.ones((T,))
c= np.zeros(int((n-T)/2,))
a1 = np.append(a,b)
a2 = np.append(a1,c)
return a2
x =rect(11,6)
plt.step(x, 'r')
plt.show()
This is so far that I wrote. Appreciate anyone can give the Idea
A method to center the rectangle at x=0 is to provide x values to plt.step. One way to accomplish this is to use numpy arange and center the x values around 0 by using the length of a2 returned in the rects function
# Changed to y because it will be our y values in plt.step
y = rect(11, 6)
# Add 0.5 so it's centered
x = np.arange(-len(y)/2 + 0.5, len(y)/2 + 0.5)
And then plot it using plt.step and setting where to mid (more info in the plt.step docs):
plt.step(x, y, where='mid', color='r')
Hope this helps. Here is the full code:
import numpy as np
import matplotlib.pyplot as plt
def rect(n, T):
a = np.zeros(int((n-T)/2,))
b = np.ones((T,))
c = np.zeros(int((n-T)/2,))
a1 = np.append(a, b)
a2 = np.append(a1, c)
return a2
y = rect(11, 6)
# Add 0.5 so it's centered
x = np.arange(-len(y)/2 + 0.5, len(y)/2 + 0.5)
plt.step(x, y, where='mid', color='r')
plt.show()

Prevent 'darkgrid' ax2 gridlines in twinx() plot from disecting ax1 curve

I am having a problem with preventing grid lines in 'darkgrid' from disecting a line associated with the X1 axis when plotting a twinx() plot. I can "fix" the problem by not using 'darkgrid' or by passing an empty list to X2 (and lose the axis labels to - se last line), but I do want 'darkgrid' and x2 axis labels.
#Some imports
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
sns.set_style("darkgrid")
%matplotlib inline
#Data
d = np.arange(0, 1000, 100)
x1 = d/30 #redmodel
x2 = np.sqrt(d) #bluemodel
#Figure
fig = plt.figure(figsize = (8, 12))
sy1 = 'r-' #redmodel
sy2 = 'b-' #bluemodel
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()
_ = ax1.plot(x1, d, sy1)
_ = ax1.set_ylabel('D')
_ = ax1.set_ylim(0, 1000)
_ = ax1.set_xlabel('X1')
_ = ax1.set_xlim(0, 31)
_ = ax2.plot(x2, d, sy2)
_ = ax2.set_xlabel('X2')
_ = ax2.set_xlim(0, 31)
#_ = ax2.set_xticks([]) #Empty list passed to omit_xticks, otherwise ax2 gridines disect red line
As I was looking for solutions to this problem I stumbled upon the axes_grid1 toolkit collection of helper classes which has the twin() option (in addition to twinx and twiny) which may be the solution to my problem. But if you know of a simpler one please help me out.
The intent of your question is to answer as the challenge is to draw the grid lines of the x2 axis across the red line. I think you can simply set a standard for the grid lines of the x2 axis.
_ = ax2.grid(which='major', axis='x', zorder=1.0)

Is there a way to fit a normal curve to points?

As a small project I've made a program the throws nd dice an nt number of times. At each throw it sums the results from the dice and adds it to a list. At the end the data is rappresented with matplot.
import random
from collections import Counter
import matplotlib.pyplot as plt
nd = int(input("Insert number of dice: "))
nt = int(input("Insert number of throws: "))
print(nd, " dice thrown ", nt, " times")
print("Generating sums, please hold....")
c = 0
i = 0
sum = 0
sums = []
while nt >= i :
while nd >= c:
g = random.randint(1, 6)
sum = sum + g
c += 1
sums.append(sum)
i = i+1
c=0
sum = 0
print("Throw ", i, " of ", nt)
sums.sort()
max = max(sums)
min = min(sums)
print("||Maximum result: ", max, " ||Minimum result: ", min)
print("Now ordering results")
f = Counter(sums)
y = list(f.values())
x = list(f.keys())
print("Rappresenting results")
plt.plot(x, y)
plt.xlabel("Risultati")
plt.ylabel("Frequenza")
plt.title("Distribuzione delle somme")
plt.grid(True)
plt.tight_layout()
plt.show()
The resultant graph looks something like this:
I would like to know how to fit a gaussian curve to the points in order to make the graph clearer
The mean and the standard deviation of the sums are the parameters needed for the Gaussian normal. The pdf of a distribution has an area of 1. To scale it to the same size as the histogram, it needs to be multiplied with the number of input values (len(sums)).
Converting the code to work with numpy arrays, makes everything much faster:
import numpy as np
from collections import Counter
import matplotlib.pyplot as plt
from scipy.stats import norm
nd = 10000 # int(input("Insert number of dice: "))
nt = 10000 # int(input("Insert number of throws: "))
print(nd, "dice thrown", nt, "times")
print("Generating sums, please hold....")
sums = np.zeros(nt, dtype=np.int)
for i in range(nt):
sums[i] = np.sum(np.random.randint(1, 7, nd))
sums.sort()
xmax = sums.max()
xmin = sums.min()
print("||Maximum result: ", xmax, " ||Minimum result: ", xmin)
print("Now ordering results")
f = Counter(sums)
y = list(f.values())
x = list(f.keys())
print("Plotting results")
plt.plot(x, y)
mean = sums.mean()
std = sums.std()
xs = np.arange(xmin, xmax + 1)
plt.plot(xs, norm.pdf(xs, mean, std) * len(sums), color='red', alpha=0.7, lw=3)
plt.margins(x=0)
plt.xlim(xmin, xmax)
plt.ylim(ymin=0)
plt.tight_layout()
plt.show()
PS: Here is some code to add to the code of the question, using numpy only for calculating the mean and the standard deviation. (Note that as you use sum as a variable name, you get an error when you try to use Python's sum() function. Therefore, it is highly recommended to avoid naming variables such as sum and max.)
def f(x):
return norm.pdf(x, mean, std) * len(sums)
mean = np.mean(sums)
std = np.std(sums)
xs = range(xmin, xmax+1)
ys = [f(x) for x in xs]
plt.plot(xs, ys, color='red', lw=3)

matplotlib - plotting histogram with unique bins

I am trying to plot a histogram but the x ticks does not seem to get right.
The plot is intended to get a histogram of frequency counts ( 1 to 13 ) and total rows in 10000.
d1 = []
for i in np.arange(1, 10000):
tmp = np.random.randint(1, 13)
d1.append(tmp)
d2 = pd.DataFrame(d1)
d2.hist(width = 0.5)
plt.xticks(np.arange(1, 14, 1))
I am trying to plot frequency count of values and not ranges.
You would need to set the bin edges which should be used by the histogram.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
d1 = np.random.randint(1, 13, size=1000)
d2 = pd.DataFrame(d1)
bins = np.arange(0,13)+0.5
d2.hist(bins=bins, ec ="k")
plt.xticks(np.arange(1, 13))
plt.show()

matplotlib scatter plot using axes object in loop

I am having trouble using Matplotlib to plot multiple series in a loop (Matplotlib 1.0.0, Python 2.6.5, ArcGIS 10.0). Forum research pointed me to application of an Axes object, in order to plot multiple series on the same plot. I see how this works well for data generated outside of a loop (sample scripts), but when I insert the same syntax and add the second series into my loop that pulls data from database, I get the following error:
": unsupported operand type(s) for -: 'NoneType' and 'NoneType' Failed to execute (ChartAge8)."
Below is my code - any suggestions or comments are much appreciated!
import arcpy
import os
import matplotlib
import matplotlib.pyplot as plt
#Variables
FC = arcpy.GetParameterAsText(0) #feature class
P1_fld = arcpy.GetParameterAsText(1) #score field to chart
P2_fld = arcpy.GetParameterAsText(2) #score field to chart
plt.subplots_adjust(hspace=0.4)
nsubp = int(arcpy.GetCount_management(FC).getOutput(0)) #pulls n subplots from FC
last_val = object()
#Sub-plot loop
cur = arcpy.SearchCursor(FC, "", "", P1_fld)
i = 0
x1 = 1 # category 1 locator along x-axis
x2 = 2 # category 2 locator along x-axis
fig = plt.figure()
for row in cur:
y1 = row.getValue(P1_fld)
y2 = row.getValue(P2_fld)
i += 1
ax1 = fig.add_subplot(nsubp, 1, i)
ax1.scatter(x1, y1, s=10, c='b', marker="s")
ax1.scatter(x2, y2, s=10, c='r', marker="o")
del row, cur
#Save plot to pdf, open
figPDf = r"path.pdf"
plt.savefig(figPDf)
os.startfile("path.pdf")
If what you want to do is plot several stuff reusing the same plot what you should do it create the figure object outside the loop and then plot to that same object everytime, something like this:
fig = plt.figure()
for row in cur:
y1 = row.getValue(P1_fld)
y2 = row.getValue(P2_fld)
i += 1
ax1 = fig.add_subplot(nsubp, 1, i)
ax1.scatter(x1, y1, s=10, c='b', marker="s")
ax1.scatter(x2, y2, s=10, c='r', marker="o")
del row, cur