connect two points of a plot with another line - python-3.x

I want to connect two points in a data frame plot with another line and add it to the plot:
import numpy as np
from numpy.random import randn
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt
%matplotlib inline
days = [datetime(2016, 1, 1), datetime(2016, 1, 2),datetime(2016, 1, 3),datetime(2016, 1, 4)]
dt_ind = pd.DatetimeIndex(days)
data = np.random.randn(4,2)
cols = ['A','B']
df = pd.DataFrame(data,dt_ind,cols)
df['A'].plot(figsize=(12,4), sort_columns=True)
here is the data frame:
enter image description here
and the plot:
enter image description here
how is that possible? for example add a line from point 2 to point 4 (or any two points)

You want to use matplotlib's plt.subplots() function to return a fig and ax object, so you can then add separate lines to your ax.
import numpy as np
from numpy.random import randn
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt
%matplotlib inline
days = [datetime(2016, 1, 1),
datetime(2016, 1, 2),
datetime(2016, 1, 3),
datetime(2016, 1, 4)]
dt_ind = pd.DatetimeIndex(days)
data = np.random.randn(4,2)
cols = ['A','B']
df = pd.DataFrame(data,dt_ind,cols)
fig, ax = plt.subplots()
ax.plot(df['A'], color='red')
ax.plot([df.index[1], df.index[3]],
[df['A'][1], df['A'][3]], color='blue')

Related

How to show all dates in matplotlib from excel import?

I have a code in python 3.11 for a contour plot generating from an excel table using matplotlib. The result shows only first days of months on the x axis (for example 1.6.2022, 1.7.2022 ...). I want all days from the excel source table. Her's the code:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import Normalize
import pandas as pd
import matplotlib.dates as mdates
# import data from excel file
df = pd.read_excel('temperature_data.xlsx', index_col=0)
# Assign columns to variables
time = df.columns
depth = df.index
temperature = df.to_numpy()
# Creating the graph
fig, ax = plt.subplots()
min_temp = temperature.min()
max_temp = temperature.max()
cs = plt.contourf(time, depth, temperature, levels=np.arange(round(min_temp), round(max_temp)+2, 2), cmap='coolwarm', vmin=min_temp, vmax=max_temp)
cs2 = plt.contour(time, depth, temperature, levels=np.arange(round(min_temp), round(max_temp)+2, 2), colors='black')
plt.gca().invert_yaxis()
plt.clabel(cs2, inline=1, fontsize=10, fmt='%d')
plt.title('Teplota vody [°C]')
plt.xticks(rotation=90, ha='right')
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%Y'))
#ax.set_xlim(df.index.min(), df.index.max())
#ax.set_xlabel('Time')
ax.set_ylabel('hloubka [m]')
norm = Normalize(vmin=min_temp, vmax=max_temp)
plt.colorbar(cs, cmap='coolwarm', norm=norm)
plt.show()
Thank you for your help.

Can I generate a contourplot from three columns of data in python without using meshgrid?

I have three columns of data. They are too large to generate meshgrids from. So e.g. in order to generate a surface plot from the data, I use a method like so
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
x, y, z = np.loadtxt('data_file', unpack=True)
df = pd.DataFrame({'x':x, 'y':y, 'z':z})
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_trisurf(df.x, df.y, df.z, cmap=cm.jet, linewidth=0.05)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
Is there a similar alternative to plot_trisurf for contours?

How to select window_length and polyorder in scipy.signal.savgol_filter for a daily data

Say if I would like to smooth the the following daily data named oildata with scipy.signal.savgol_filter:
from scipy.signal import savgol_filter
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
data = np.random.uniform(0, 10, size=90)
index= pd.date_range('20130226', periods=90)
oildata = pd.Series(data, index)
savgol_filter(oildata, 5, 3)
plt.plot(oildata)
plt.plot(pd.Series(savgol_filter(oildata, 5, 3), index=oildata.index))
plt.show()
Out:
Out:
When I replace savgol_filter(oildata, 5, 3) to savgol_filter(oildata, 31, 3):
Beside trial and error methods, I wonder if there are any criteria or methods to select a suitable window_length (which must be a positive odd integer) and polyorder (must be less than window_length) pairs quickly? Thanks.
Reference:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.savgol_filter.html

How to add color and legend by points' label one by one in python?

I want to divide and color points,val_lab(611,3) by their labels,pred_LAB(611,)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = plt.axes(projection = '3d')
ax.set_xlabel('L')
ax.set_ylabel('A')
ax.set_zlabel('B')
for i in range(0, len(val_lab)):
ax.scatter3D(
val_lab[i,0],
val_lab[i,1],
val_lab[i,2],
s = 8,
marker='o',
c = pred_LAB
#cmap = 'rainbow'
)
#ax.legend(*points.legend_elements(), title = 'clusters')
plt.show()
The problem is it shows error,
c' argument has 611 elements, which is not acceptable for use with 'x'
with size 1, 'y' with size 1.
However, if the dataset only have ten points,it can show the figure correctly, I don't know how to solve this problem, besides, how to add legend of this figure?
In your solution you would want to replace c = pred_LAB with c = pred_LAB[i]. But you do not have to use a for loop to plot the data. You can just use the following:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# generate random input data
val_lab = np.random.randint(0,10,(611,3))
pred_LAB = np.random.uniform(0,1, (611,))
# plot data
fig = plt.figure()
ax = plt.axes(projection = '3d')
ax.set_xlabel('L')
ax.set_ylabel('A')
ax.set_zlabel('B')
# create one 3D scatter plot - no for loop
ax.scatter3D(
val_lab[:,0],
val_lab[:,1],
val_lab[:,2],
s = 8,
marker='o',
c = pred_LAB,
cmap = 'rainbow',
label='my points'
)
# add legend
plt.legend()
plt.show()

Pandas to MatPlotLib with Dollar Signs

Given the following data frame:
import pandas as pd
df=pd.DataFrame({'A':['$0-$20','$20+']})
df
A
0 0−20
1 $20+
I'd like to create a bar chart in MatPlotLib but I can't seem to get the dollar signs to show up correctly.
Here's what I have:
import matplotlib.pyplot as plt
import numpy as np
y=df.B
x=df.A
ind=np.arange(len(x))
fig, ax = plt.subplots(1, 1, figsize = (2,2))
plt.bar(ind, y, align='center', width=.5, edgecolor='none', color='grey')
ax.patch.set_facecolor('none')
ax.patch.set_alpha(0)
ax.set_ylim([0,5])
ax.set_xlabel(x,fontsize=12,rotation=0,color='grey')
ax.set_xticklabels('')
ax.set_yticklabels('')
I can get the labels to display "better" if I use df.A.values.tolist(), but that just corrects the format.
I'd like each label to display under each bar with the intended original format (with dollar signs).
Thanks in advance!
To specify the xticklabels, pass tick_label=x to plt.bar.
Matplotlib parses labels using a subset of the TeX markup
language. Dollar
signs indicate the beginning (and end) of math mode. So pairs of bare dollar signs are
getting unintentionally swallowed. Currently, there is no a way to disable mathtex parsing. So to prevent the dollar signs from being interpreted as math markup, replace the
bare $ with \$:
df['A'] = df['A'].str.replace('$', '\$')
For example,
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'A': ['$0-$20', '$20+'], 'B': [10,20]})
df['A'] = df['A'].str.replace('$', '\$')
y = df['B']
x = df['A']
ind = np.arange(len(x))
fig, ax = plt.subplots(1, 1, figsize=(2, 2))
plt.bar(ind, y,
tick_label=x,
align='center', width=.5, edgecolor='none',
color='grey')
plt.show()
Alternatively, you could use df.plot(kind='bar'):
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'A': ['$0-$20', '$20+'], 'B': [10,20]})
df['A'] = df['A'].str.replace('$', '\$')
fig, ax = plt.subplots(1, 1, figsize=(2, 2))
df.plot(kind='bar', x='A', y='B',
align='center', width=.5, edgecolor='none',
color='grey', ax=ax)
plt.xticks(rotation=25)
plt.show()

Resources