Python 子图中的范围类似于 MATLAB 堆积图 ()
Scope in Python subplot similar to MATLAB's stackedplot()
Python 中是否有与 MATLAB 的 stackedplot()
相同的绘图函数?
stackedplot()
在 MATLAB 中可以用线图绘制具有相同 X 轴的几个变量并垂直堆叠。此外,此图中有一个范围,只需移动光标即可显示给定 X
的所有变量的值(请参阅附图)。我已经能够在 Python 中生成堆叠的子图,没有任何问题,但是,无法添加这样的范围,通过移动光标显示所有变量的值。此功能在 Python 中可用吗?
这是使用 MATLAB 的绘图 stackedplot()
:
import pandas as pd
import numpy as np
from datetime import datetime, date, time
import matplotlib.pyplot as plt
import matplotlib
import matplotlib.transforms as transforms
import mplcursors
from collections import Counter
import collections
def flatten(x):
result = []
for el in x:
if isinstance(x, collections.Iterable) and not isinstance(el, str):
result.extend(flatten(el))
else:
result.append(el)
return result
def shared_scope(sel):
sel.annotation.set_visible(False) # hide the default annotation created by mplcursors
x = sel.target[0]
for ax in axes:
for plot in plotStore:
da = plot.get_ydata()
if type(da[0]) is np.datetime64: #pd.Timestamp
yData = matplotlib.dates.date2num(da) # to numerical values
vals = np.interp(x, plot.get_xdata(), yData)
dates = matplotlib.dates.num2date(vals) # to matplotlib dates
y = datetime.strftime(dates,'%Y-%m-%d %H:%M:%S') # to strings
annot = ax.annotate(f'{y:.30s}', (x, vals), xytext=(15, 10), textcoords='offset points',
bbox=dict(facecolor='tomato', edgecolor='black', boxstyle='round', alpha=0.5))
sel.extras.append(annot)
else:
y = np.interp(x, plot.get_xdata(), plot.get_ydata())
annot = ax.annotate(f'{y:.2f}', (x, y), xytext=(15, 10), textcoords='offset points', arrowprops=dict(arrowstyle="->",connectionstyle="angle,angleA=0,angleB=90,rad=10"),
bbox=dict(facecolor='tomato', edgecolor='black', boxstyle='round', alpha=0.5))
sel.extras.append(annot)
vline = ax.axvline(x, color='k', ls=':')
sel.extras.append(vline)
trans = transforms.blended_transform_factory(axes[0].transData, axes[0].transAxes)
text1 = axes[0].text(x, 1.01, f'{x:.2f}', ha='center', va='bottom', color='blue', clip_on=False, transform=trans)
sel.extras.append(text1)
# Data to plot
data = pd.DataFrame(columns = ['timeOfSample','Var1','Var2'])
data.timeOfSample = ['2020-05-10 09:09:02','2020-05-10 09:09:39','2020-05-10 09:40:07','2020-05-10 09:40:45','2020-05-12 09:50:45']
data['timeOfSample'] = pd.to_datetime(data['timeOfSample'])
data.Var1 = [10,50,100,5,25]
data.Var2 = [20,55,70,60,50]
variables = ['timeOfSample',['Var1','Var2']] # variables to plot - Var1 and Var2 to share a plot
nPlot = len(variables)
dataPts = np.arange(0, len(data[variables[0]]), 1) # x values for plots
plotStore = [0]*len(flatten(variables)) # to store all the plots for annotation purposes later
fig, axes = plt.subplots(nPlot,1,sharex=True)
k=0
for i in range(nPlot):
if np.size(variables[i])==1:
yData = data[variables[i]]
line, = axes[i].plot(dataPts,yData,label = variables[i])
plotStore[k]=line
k = k+1
else:
for j in range(np.size(variables[i])):
yData = data[variables[i][j]]
line, = axes[i].plot(dataPts,yData,label = variables[i][j])
plotStore[k]=line
k = k+1
axes[i].set_ylabel(variables[i])
cursor = mplcursors.cursor(plotStore, hover=True)
cursor.connect('add', shared_scope)
plt.xlabel('Samples')
plt.show()
mplcursors 可用于在悬停、移动文本和垂直条时创建注释。 sel.extras.append(...)
有助于自动隐藏不再需要的元素。
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
import mplcursors
import numpy as np
def shared_scope(sel):
x = sel.target[0]
annotation_text = f'x: {x:.2f}'
for ax, plot in zip(axes, all_plots):
y = np.interp(x, plot.get_xdata(), plot.get_ydata())
annotation_text += f'\n{plot.get_label()}: {y:.2f}'
vline = ax.axvline(x, color='k', ls=':')
sel.extras.append(vline)
sel.annotation.set_text(annotation_text)
trans = transforms.blended_transform_factory(axes[0].transData, axes[0].transAxes)
text1 = axes[0].text(x, 1.01, f'{x:.2f}', ha='center', va='bottom', color='blue', clip_on=False, transform=trans)
sel.extras.append(text1)
fig, axes = plt.subplots(figsize=(15, 10), nrows=3, sharex=True)
y1 = np.random.uniform(-1, 1, 100).cumsum()
y2 = np.random.uniform(-1, 1, 100).cumsum()
y3 = np.random.uniform(-1, 1, 100).cumsum()
all_y = [y1, y2, y3]
all_labels = ['Var1', 'Var2', 'Var3']
all_plots = [ax.plot(y, label=label)[0]
for ax, y, label in zip(axes, all_y, all_labels)]
for ax, label in zip(axes, all_labels):
ax.set_ylabel(label)
cursor = mplcursors.cursor(all_plots, hover=True)
cursor.connect('add', shared_scope)
plt.show()
这是一个版本,每个子图都有单独的注释:
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
import mplcursors
import numpy as np
def shared_scope(sel):
sel.annotation.set_visible(False) # hide the default annotation created by mplcursors
x = sel.target[0]
for ax, plot in zip(axes, all_plots):
y = np.interp(x, plot.get_xdata(), plot.get_ydata())
vline = ax.axvline(x, color='k', ls=':')
sel.extras.append(vline)
annot = ax.annotate(f'{y:.2f}', (x, y), xytext=(5, 0), textcoords='offset points',
bbox=dict(facecolor='tomato', edgecolor='black', boxstyle='round', alpha=0.5))
sel.extras.append(annot)
trans = transforms.blended_transform_factory(axes[0].transData, axes[0].transAxes)
text1 = axes[0].text(x, 1.01, f'{x:.2f}', ha='center', va='bottom', color='blue', clip_on=False, transform=trans)
sel.extras.append(text1)
fig, axes = plt.subplots(figsize=(15, 10), nrows=3, sharex=True)
y1 = np.random.uniform(-1, 1, 100).cumsum()
y2 = np.random.uniform(-1, 1, 100).cumsum()
y3 = np.random.uniform(-1, 1, 100).cumsum()
all_y = [y1, y2, y3]
all_labels = ['Var1', 'Var2', 'Var3']
all_plots = [ax.plot(y, label=label)[0]
for ax, y, label in zip(axes, all_y, all_labels)]
for ax, label in zip(axes, all_labels):
ax.set_ylabel(label)
cursor = mplcursors.cursor(all_plots, hover=True)
cursor.connect('add', shared_scope)
plt.show()
Python 中是否有与 MATLAB 的 stackedplot()
相同的绘图函数?
stackedplot()
在 MATLAB 中可以用线图绘制具有相同 X 轴的几个变量并垂直堆叠。此外,此图中有一个范围,只需移动光标即可显示给定 X
的所有变量的值(请参阅附图)。我已经能够在 Python 中生成堆叠的子图,没有任何问题,但是,无法添加这样的范围,通过移动光标显示所有变量的值。此功能在 Python 中可用吗?
这是使用 MATLAB 的绘图 stackedplot()
:
import pandas as pd
import numpy as np
from datetime import datetime, date, time
import matplotlib.pyplot as plt
import matplotlib
import matplotlib.transforms as transforms
import mplcursors
from collections import Counter
import collections
def flatten(x):
result = []
for el in x:
if isinstance(x, collections.Iterable) and not isinstance(el, str):
result.extend(flatten(el))
else:
result.append(el)
return result
def shared_scope(sel):
sel.annotation.set_visible(False) # hide the default annotation created by mplcursors
x = sel.target[0]
for ax in axes:
for plot in plotStore:
da = plot.get_ydata()
if type(da[0]) is np.datetime64: #pd.Timestamp
yData = matplotlib.dates.date2num(da) # to numerical values
vals = np.interp(x, plot.get_xdata(), yData)
dates = matplotlib.dates.num2date(vals) # to matplotlib dates
y = datetime.strftime(dates,'%Y-%m-%d %H:%M:%S') # to strings
annot = ax.annotate(f'{y:.30s}', (x, vals), xytext=(15, 10), textcoords='offset points',
bbox=dict(facecolor='tomato', edgecolor='black', boxstyle='round', alpha=0.5))
sel.extras.append(annot)
else:
y = np.interp(x, plot.get_xdata(), plot.get_ydata())
annot = ax.annotate(f'{y:.2f}', (x, y), xytext=(15, 10), textcoords='offset points', arrowprops=dict(arrowstyle="->",connectionstyle="angle,angleA=0,angleB=90,rad=10"),
bbox=dict(facecolor='tomato', edgecolor='black', boxstyle='round', alpha=0.5))
sel.extras.append(annot)
vline = ax.axvline(x, color='k', ls=':')
sel.extras.append(vline)
trans = transforms.blended_transform_factory(axes[0].transData, axes[0].transAxes)
text1 = axes[0].text(x, 1.01, f'{x:.2f}', ha='center', va='bottom', color='blue', clip_on=False, transform=trans)
sel.extras.append(text1)
# Data to plot
data = pd.DataFrame(columns = ['timeOfSample','Var1','Var2'])
data.timeOfSample = ['2020-05-10 09:09:02','2020-05-10 09:09:39','2020-05-10 09:40:07','2020-05-10 09:40:45','2020-05-12 09:50:45']
data['timeOfSample'] = pd.to_datetime(data['timeOfSample'])
data.Var1 = [10,50,100,5,25]
data.Var2 = [20,55,70,60,50]
variables = ['timeOfSample',['Var1','Var2']] # variables to plot - Var1 and Var2 to share a plot
nPlot = len(variables)
dataPts = np.arange(0, len(data[variables[0]]), 1) # x values for plots
plotStore = [0]*len(flatten(variables)) # to store all the plots for annotation purposes later
fig, axes = plt.subplots(nPlot,1,sharex=True)
k=0
for i in range(nPlot):
if np.size(variables[i])==1:
yData = data[variables[i]]
line, = axes[i].plot(dataPts,yData,label = variables[i])
plotStore[k]=line
k = k+1
else:
for j in range(np.size(variables[i])):
yData = data[variables[i][j]]
line, = axes[i].plot(dataPts,yData,label = variables[i][j])
plotStore[k]=line
k = k+1
axes[i].set_ylabel(variables[i])
cursor = mplcursors.cursor(plotStore, hover=True)
cursor.connect('add', shared_scope)
plt.xlabel('Samples')
plt.show()
mplcursors 可用于在悬停、移动文本和垂直条时创建注释。 sel.extras.append(...)
有助于自动隐藏不再需要的元素。
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
import mplcursors
import numpy as np
def shared_scope(sel):
x = sel.target[0]
annotation_text = f'x: {x:.2f}'
for ax, plot in zip(axes, all_plots):
y = np.interp(x, plot.get_xdata(), plot.get_ydata())
annotation_text += f'\n{plot.get_label()}: {y:.2f}'
vline = ax.axvline(x, color='k', ls=':')
sel.extras.append(vline)
sel.annotation.set_text(annotation_text)
trans = transforms.blended_transform_factory(axes[0].transData, axes[0].transAxes)
text1 = axes[0].text(x, 1.01, f'{x:.2f}', ha='center', va='bottom', color='blue', clip_on=False, transform=trans)
sel.extras.append(text1)
fig, axes = plt.subplots(figsize=(15, 10), nrows=3, sharex=True)
y1 = np.random.uniform(-1, 1, 100).cumsum()
y2 = np.random.uniform(-1, 1, 100).cumsum()
y3 = np.random.uniform(-1, 1, 100).cumsum()
all_y = [y1, y2, y3]
all_labels = ['Var1', 'Var2', 'Var3']
all_plots = [ax.plot(y, label=label)[0]
for ax, y, label in zip(axes, all_y, all_labels)]
for ax, label in zip(axes, all_labels):
ax.set_ylabel(label)
cursor = mplcursors.cursor(all_plots, hover=True)
cursor.connect('add', shared_scope)
plt.show()
这是一个版本,每个子图都有单独的注释:
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
import mplcursors
import numpy as np
def shared_scope(sel):
sel.annotation.set_visible(False) # hide the default annotation created by mplcursors
x = sel.target[0]
for ax, plot in zip(axes, all_plots):
y = np.interp(x, plot.get_xdata(), plot.get_ydata())
vline = ax.axvline(x, color='k', ls=':')
sel.extras.append(vline)
annot = ax.annotate(f'{y:.2f}', (x, y), xytext=(5, 0), textcoords='offset points',
bbox=dict(facecolor='tomato', edgecolor='black', boxstyle='round', alpha=0.5))
sel.extras.append(annot)
trans = transforms.blended_transform_factory(axes[0].transData, axes[0].transAxes)
text1 = axes[0].text(x, 1.01, f'{x:.2f}', ha='center', va='bottom', color='blue', clip_on=False, transform=trans)
sel.extras.append(text1)
fig, axes = plt.subplots(figsize=(15, 10), nrows=3, sharex=True)
y1 = np.random.uniform(-1, 1, 100).cumsum()
y2 = np.random.uniform(-1, 1, 100).cumsum()
y3 = np.random.uniform(-1, 1, 100).cumsum()
all_y = [y1, y2, y3]
all_labels = ['Var1', 'Var2', 'Var3']
all_plots = [ax.plot(y, label=label)[0]
for ax, y, label in zip(axes, all_y, all_labels)]
for ax, label in zip(axes, all_labels):
ax.set_ylabel(label)
cursor = mplcursors.cursor(all_plots, hover=True)
cursor.connect('add', shared_scope)
plt.show()