Matlab- graphing and subplots [closed] - string

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I tried to do my homework and i'm not sure if I did it right. I'm not entirely sure how linspace works and was hoping for some input on my code! I'll attach the assignment it's based on. [enter link description here][1]
[enter image description here][2]
clc
clear all
figure(1);
figure(1);
x = 0:0.1:10
y1 = exp(-0.5*x).*sin(2*x)
y2 = exp(-0.5*x).*cos(2*x)
plot(x,y1,'-b',x,y2,'--r')
legend('y1','y2');
grid on
xlabel('\bfx axis');
ylabel('\bfy axis');
title('Sin and Cos Functions')
figure(2);
subplot(2,2,1)
plot(x,y1,'-b');
legend('y1','Location','northeast');
grid on
xlabel('\bfx')
ylabel('\bfy1')
title('Subplot of x and y1')
figure(3)
subplot(2,2,2)
plot(x,y2,'--r');
legend('y2','Location','northeast');
grid on
xlabel('\bfx')
ylabel('\bfy2')
title('Subplot of x and y2')
figure(4)
x = linspace(-2,8,200);
fun=(x.^2-6*x+5)./(x-3)
plot(x,fun,'b-','LineWidth',2)
axis([-2 8 -10 10]);
hold on;
title('Plot of f(x)')
xlabel('\bfx')
ylabel('\bfy')
(50 Points) Plot the function y(x) = (e^-0.5x)(Sin2x) for 100 values of x between 0 and 10. Use solid blue line for this function. Then plot the function y(x) = (e^-0.5x)(Cos2x)on the same axis. Use dashed red line for this function. Be sure to include a legend, title, axis labels and grid on the plots. Re-graph the two functions using subplot.
(50 Points) Plot the function Plot the function f(x)= ((X^2)-6x-5)/(x-3) using 200 points over the range −2 ≤ x ≤ 8. Note that there is an asymptote at x = 3, so the function will tent to infinity near to that point. In order to see the rest of the plot properly, you will need to limit the y-axis to the range -10 to 10.

linspace takes 3 arguments: a starting value, an ending value, and n = the number of points you want to generate in between those two numbers. It outputs an array of n evenly spaced numbers between your starting and ending values. For example linspace(0, 10, 5) returns an array of 5 evenly spaced numbers starting with 0 and ending with 10.
Here's the code for figure 1
x = linspace(0, 10, 100);
y1 = exp(-0.5*x).*sin(2*x);
y2 = exp(-0.5*x).*cos(2*x);
figure(1)
plot(x, y1, '-b', x, y2, '--r')
title('This is the title')
legend('This is Y1', 'This is Y2')
xlabel('These are the X values')
ylabel('These are the Y values')
grid on
Figure 2. Both subplots can be under one figure handle (i.e. figure(2)).
figure(2)
subplot(2, 1, 1)
plot(x, y1, '-b')
title('This is the first subplot')
xlabel('X axis')
ylabel('Y axis')
grid on
subplot(2, 1, 2)
plot(x, y2, '--r')
title('This is the second subplot')
xlabel('Another X axis')
ylabel('Another Y axis')
grid on
Figure 3. Your code looks right. Here's a similar solution:
x2 = linspace(-2, 8, 200);
y3 = ((x2.^2)-6.*x2-5)./(x2-3);
figure(3)
plot(x2, y3, '-g')
title('The third figure')
grid on
ylim([-10 10])
xlabel('Another axis')
ylabel('The last axis')

Related

How to add count on top of bars in seaborn catplot? [duplicate]

This question already has answers here:
How to add value labels on a bar chart
(7 answers)
Closed 8 months ago.
I have a dataframe that looks like:
User A B C
ABC 100 121 OPEN
BCD 200 255 CLOSE
BCD 500 134 OPEN
DEF 600 125 CLOSE
ABC 900 632 OPEN
ABC 150 875 CLOSE
DEF 690 146 OPEN
I am trying to display a countplot on column 'User'. The code is as follows:
fig, ax1 = plt.subplots(figsize=(20,10))
graph = sns.countplot(ax=ax1,x='User', data=df)
graph.set_xticklabels(graph.get_xticklabels(),rotation=90)
for p in graph.patches:
height = p.get_height()
graph.text(p.get_x()+p.get_width()/2., height + 0.1,
'Hello',ha="center")
The output looks like:
However, I want to replace string 'Hello' with the value_counts of column 'User'. When I add the code to add label to graph :
for p in graph.patches:
height = p.get_height()
graph.text(p.get_x()+p.get_width()/2., height + 0.1,
df['User'].value_counts(),ha="center")
I get the output as:
New in matplotlib 3.4.0
We can now automatically annotate bar plots with the built-in Axes.bar_label, so all we need to do is access/extract the seaborn plot's Axes.
Seaborn offers several ways to plot counts, each with slightly different count aggregation and Axes handling:
seaborn.countplot (most straightforward)
This automatically aggregates counts and returns an Axes, so just directly label ax.containers[0]:
ax = sns.countplot(x='User', data=df)
ax.bar_label(ax.containers[0])
seaborn.catplot (kind='count')
This plots a countplot onto a facet grid, so extract the Axes from the grid before labeling ax.containers[0]:
g = sns.catplot(x='User', kind='count', data=df)
for ax in g.axes.flat:
ax.bar_label(ax.containers[0])
seaborn.barplot
This returns an Axes but does not aggregate counts, so first compute Series.value_counts before labeling ax.containers[0]:
counts = df['User'].value_counts().rename_axis('user').reset_index(name='count')
ax = sns.barplot(x='user', y='count', data=counts)
ax.bar_label(ax.containers[0])
If you are using hue:
hue plots will contain multiple bar containers, so ax.containers will need to be iterated:
ax = sns.countplot(x='User', hue='C', data=df)
for container in ax.containers:
ax.bar_label(container)
df['User'].value_counts() will return a Series containing counts of unique values of the column User.
Without analyzing in much detail your code, you could correct it by indexing the result of value_counts with a counter:
fig, ax1 = plt.subplots(figsize=(20,10))
graph = sns.countplot(ax=ax1,x='User', data=df)
graph.set_xticklabels(graph.get_xticklabels(),rotation=90)
i=0
for p in graph.patches:
height = p.get_height()
graph.text(p.get_x()+p.get_width()/2., height + 0.1,
df['User'].value_counts()[i],ha="center")
i += 1
With your sample data, it produces the following plot:
As suggested by #ImportanceOfBeingErnest, the following code produces the same output with simpler code, using the height variable itself instead of the value_counts indexed:
fig, ax1 = plt.subplots(figsize=(20,10))
graph = sns.countplot(ax=ax1,x='User', data=df)
graph.set_xticklabels(graph.get_xticklabels(),rotation=90)
for p in graph.patches:
height = p.get_height()
graph.text(p.get_x()+p.get_width()/2., height + 0.1,height ,ha="center")
other solution
#data
labels=data['Sistema Operativo'].value_counts().index
values=data['Sistema Operativo'].value_counts().values
plt.figure(figsize = (15, 8))
ax = sns.barplot(x=labels, y=values)
for i, p in enumerate(ax.patches):
height = p.get_height()
ax.text(p.get_x()+p.get_width()/2., height + 0.1, values[i],ha="center")
Chart Image
Note: This solution does not try to show the count on top of the bar. Instead, this simple solution will print the values inside the bar. This may be an elegant solution for some occasions.
import seaborn as sns
ax=sns.countplot(x=df['category'], data=df);
for p in ax.patches:
ax.annotate(f'\n{p.get_height()}', (p.get_x()+0.2, p.get_height()), ha='center', va='top', color='white', size=18)

Using Matplotlib to create a simple schedule

I am trying to create a simple schedule using Matplotlib. I have the following start. I want to remove the y-axis numbers and display "a=1", "a=2", "a=3" instead. Indeed, y1 and y2 defined in my function are sort of fake because the thickness of the box does not really have to be some number. As long as I have an equal thickness for each "a," it is all fine. I want to plot a box with a shade for a=1 in between 370 and 560, for a=2 in between 550 and 980 and so on. The x-axis shows the time in minutes. I checked horizontal bar plots, but they all start from 0 and I couldn't figure out a way to convert them into a scheduling type. Any suggestions?
import matplotlib.pyplot as plt
x = [(370, 560), (550,980), (380,440)]
def activity_filler(x,y1,y2):
# Shade the area between y1 and y2
plt.fill_between(x, y1, y2,
facecolor="grey", # The fill color
color='grey', # The outline color
alpha=0.4, hatch = 'X\/|-') # Transparency of the fill
activity_filler(x[0],[1],[2])
activity_filler(x[1],[2],[3])
activity_filler(x[2],[3],[4])
plt.show()
x = [(370, 560), (550,980), (380,440)]
fig, ax = plt.subplots()
for i,evt in enumerate(x):
ax.barh(i,width=evt[1]-evt[0],left=evt[0])
ax.set_yticks(range(len(x)))
ax.set_yticklabels([f'a={i+1}' for i in range(len(x))])

How to visualize feasible region for linear programming (with arbitrary inequalities) in Numpy/MatplotLib?

I need to implement a solver for linear programming problems. All of the restrictions are <= ones such as
5x + 10y <= 10
There can be an arbitrary amount of these restrictions. Also , x>=0 y>=0 implicitly.
I need to find the optimal solutions(max) and show the feasible region in matplotlib. I've found the optimal solution by implementing the simplex method but I can't figure out how to draw the graph.
Some approaches I've found:
This link finds the minimum of the y points from each function and uses plt.fillBetween() to draw the region. But it doesn't work when I change the order of the equations. I'm not sure which y values to minimize(). So I can't use it for arbitrary restrictions.
Find solution for every pair of restrictions and draw a polygon. Not efficient.
An easier approach might be to have matplotlib compute the feasible region on its own (with you only providing the constraints) and then simply overlay the "constraint" lines on top.
# plot the feasible region
d = np.linspace(-2,16,300)
x,y = np.meshgrid(d,d)
plt.imshow( ((y>=2) & (2*y<=25-x) & (4*y>=2*x-8) & (y<=2*x-5)).astype(int) ,
extent=(x.min(),x.max(),y.min(),y.max()),origin="lower", cmap="Greys", alpha = 0.3);
# plot the lines defining the constraints
x = np.linspace(0, 16, 2000)
# y >= 2
y1 = (x*0) + 2
# 2y <= 25 - x
y2 = (25-x)/2.0
# 4y >= 2x - 8
y3 = (2*x-8)/4.0
# y <= 2x - 5
y4 = 2 * x -5
# Make plot
plt.plot(x, 2*np.ones_like(y1))
plt.plot(x, y2, label=r'$2y\leq25-x$')
plt.plot(x, y3, label=r'$4y\geq 2x - 8$')
plt.plot(x, y4, label=r'$y\leq 2x-5$')
plt.xlim(0,16)
plt.ylim(0,11)
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.xlabel(r'$x$')
plt.ylabel(r'$y$')
This is a vertex enumeration problem. You can use the function lineqs which visualizes the system of inequalities A x >= b for any number of lines. The function will also display the vertices on which the graph was plotted.
The last 2 lines mean that x,y >=0
from intvalpy import lineqs
import numpy as np
A = -np.array([[5, 10],
[-1, 0],
[0, -1]])
b = -np.array([10, 0, 0])
lineqs(A, b, title='Solution', color='gray', alpha=0.5, s=10, size=(15,15), save=False, show=True)
Visual Solution Link

How to add a forth bar on a group barchart using matplotlib and seaborn in Python?

I am trying to create a group barchart to show the accuracy, precision, recall and f1 scores achieved by different machine learning classifiers. The group bar chart works ok when I use three bars per classifier but it looks strange when I add a forth one. Specifically, the gap between the bars disappears and the forth bar overlaps with other bars. This is how it looks when I use three bars:
and this is how it looks when I try to add a forth one:
N = 9
ind = np.arange(N) # location of groups
width = 0.27 # width of bars
fig = plt.figure()
ax = fig.add_subplot(111)
rects1 = ax.bar(ind, Precision, width, color='r')
rects2 = ax.bar(ind+width, Recall, width, color='g')
rects3 = ax.bar(ind+width*2, F1, width, color='b')
rects4 = ax.bar(ind+width*3, Accuracy, width, color='y')
ax.set_ylabel('Scores')
ax.set_xticks(ind+width)
ax.set_xticklabels(Model,rotation=90)
ax.legend( (rects1[0], rects2[0], rects3[0]), ('Precision', 'Recall','F1 Score') )
def autolabel(rects):
for rect in rects:
h = rect.get_height()
ax.text(rect.get_x()+rect.get_width()/2., 1.05*h, '%d'%int(h*100),
ha='center', va='bottom')
autolabel(rects1)
autolabel(rects2)
autolabel(rects3)
autolabel(rects4)
fig_size = plt.rcParams["figure.figsize"]
fig_size[0] = 20
fig_size[1] = 15
plt.rcParams["figure.figsize"] = fig_size
plt.show()
I am new to Python so any help will be much appreciated.
The problem is that your current spacing is 0.27. When you have 4 bars, this results in 0.27*4 = 1.08 spacing, whereas the corresponding bars are spaced at a distance of 1. As a result, your bars start to overlap.
One hardcoded solution is to replace 0.27 by something smaller such as 0.2. This will leave a spacing of 1-0.2*4 = 0.2 between the adjacent bars.
Other smart solution would be to compute the spacing depending on the number of bars using something like spacing = 1/(nbars+1) where +1 is to add extra space
P.S: Python 2 users as pointed out by #Leporello
Use spacing = 1.0/(nbars+1)

points of intersection of horizontal line with a function [duplicate]

This question already has answers here:
Intersection of two graphs in Python, find the x value
(10 answers)
Closed 3 years ago.
i have this code that generate the following (image), how would i proceed to detect the intersections of the line with the function ?`
import numpy as np
import matplotlib.pyplot as plt
y = 0.4*np.ones(100)
x = np.arange(0, 100)
t = np.linspace(0,100,100)
Fs = 6000
f = 200
func = np.sin(2 * np.pi * f * t / Fs)
idx = np.where(func == y) # how i think i should do to detect intersections
print(idx)
plt.plot(x, y) # the horizontal line
plt.plot(t,func) # the function
plt.show()
You can use the following expression to get the indices of the array t that is closest to the intersection points.
idx = np.argwhere(np.diff(np.sign(y - func))).flatten()
This expression selects indices where there is a change of sign in the list. However, this is only an approximation of the real intersection points. Decrease the step-size of t to increase precision.
Since the equations are relatively simple, another way would be to solve it by hand and implement the closed-form formula for plotting.
You have the equations y = 0.4 and y = sin(2*pi*t*f/Fs). Intersection points are at values of t such that 0.4 = sin(2*pi*t*f/Fs). Solving for t gives two answers:
t = (arcsin(0.4) + 2*pi*k) / (2*pi*f/Fs)
t = (pi - arcsin(0.4) + 2*pi*k) / (2*pi*f/Fs)
where k is any integer. In short, loop through all desired integers in a given range and compute the coordinates t using the two equations above. You will get a set of points (t,0.4) that you can plot on your graph.

Resources