jupyter notebook:以交互方式更新绘图 - 函数具有常量和关键字参数
jupyter notebook: update plot interactively - function has constants and keyword arguments
我想使用 matplotlib (1.5.1) 在 jupyter (4.0.6) notebook 中创建交互式绘图。问题是静态图是用一个有四个变量的函数创建的,其中两个是常量,两个是关键字参数,我想交互式地更改关键字参数。
这可能吗?如果可以,怎么做?
下面的概念代码显示了生成绘图的函数 make_figure(...)
和生成交互式绘图的命令。
如果我将关键字参数更改为变量,则会收到错误消息 "interact() takes from 0 to 1 positional arguments but 3 were given"
概念代码:
def make_figure(const_1, const_2, var_1=0.4, var_2=0.8):
b = calc_b(var_1, var_2)
c = calc_c(b, const_1, const_2)
fig, ax = plt.subplots()
N, bins, patches = ax.hist(c)
interact(make_figure,
const_1,
const_2,
var_1=(0.2, 0.4, 0.05),
var_2=(0.75, 0.95, 0.05))
补充20160325:代码示例
我正在尝试为 class 的分数创建直方图,具体取决于分别达到 1.0 和 4.0 所需的百分比。
# setup some marks
ids_perc = np.random.random(33)
print("number of entered marks: ", ids_perc.shape)
直方图的主要代码;主要功能:get_marks
# define possible marks
marks = np.array([1.0,
1.3,
1.7,
2.0,
2.3,
2.7,
3.0,
3.3,
3.7,
4.0,
5.0])
marks_possible = marks[::-1]
def get_perc_necessary(min_perc_one,
min_perc_four,
n_marks):
"""
calculates an equally spaced array for percentage necessary to get a mark
"""
delta = (min_perc_one - min_perc_four)/(n_marks-2-1)
perc_necessary_raw = np.linspace(start=min_perc_four,
stop=min_perc_one,
num=n_marks-1)
perc_necessary = np.append([0.0], np.round(perc_necessary_raw, decimals=2))
return perc_necessary
def assign_marks(n_students,
perc_necessary,
achieved_perc,
marks_real):
"""
get the mark for each student (with a certain achieved percentage)
"""
final_marks = np.empty(n_students)
for cur_i in range(n_students):
idx = np.argmax(np.argwhere(perc_necessary <= achieved_perc[cur_i]))
final_marks[cur_i] = marks_real[idx]
return final_marks
def get_marks(achieved_perc = ids_perc,
marks_real = marks_possible,
min_perc_four = 0.15,
min_perc_one = 0.85):
n_marks = marks.shape[0]
# print("n_marks: ", n_marks)
n_students = achieved_perc.shape[0]
# print("n_students: ", n_students)
# -----------------------------
# linear step between each mark
perc_necessary = get_perc_necessary(min_perc_one,
min_perc_four,
n_marks)
# test query: there need to be as many percentages as marks
if perc_necessary.shape[0] != marks_real.shape[0]:
print("the number of marks has to be equal the number of boundaries")
raise Exception
# ------------
# assign marks
final_marks = assign_marks(n_students,
perc_necessary,
achieved_perc,
marks_real)
# ------------
# create table
fig, ax = plt.subplots()
N, bins, patches = ax.hist(final_marks,
align='mid',
bins=np.append(marks,6.)) # bins=marks
ax.xaxis.set_major_formatter(FormatStrFormatter('%0.1f'))
bin_centers = 0.5 * np.diff(bins) + bins[:-1]
ax.set_xticks(bin_centers)
ax.set_xticklabels( marks )
ax.set_xlabel("mark")
ax.set_ylabel("number of marks")
ax.set_ylim(0.0, 6.0)
plt.grid(True)
现在,当我尝试设置 interact
时
interact(get_marks,
min_perc_four=(0.2, 0.4, 0.05),
min_perc_one=(0.75, 0.95, 0.05));
我收到错误
ValueError: array([ 0.22366653, 0.74206953, 0.47501716, 0.56536227, 0.54792759,
0.60288287, 0.68548973, 0.576935 , 0.84582243, 0.40709693,
0.78600622, 0.2692508 , 0.62524819, 0.62204851, 0.5421716 ,
0.71836192, 0.97194698, 0.4054752 , 0.2185643 , 0.11786751,
0.57947848, 0.88659768, 0.38803576, 0.66617254, 0.77663263,
0.94364543, 0.23021637, 0.30899724, 0.08695842, 0.50296694,
0.8164095 , 0.77892531, 0.5542163 ]) cannot be transformed to a Widget
为什么在查看变量 ids_perc
时出现此错误?
您需要在 interact()
中明确分配您的变量。例如,像这样:
const_1 = 1
interact(make_figure,
const_1=const_1,
const_2=2,
var_1=(0.2, 0.4, 0.05),
var_2=(0.75, 0.95, 0.05))
或者(如果可能)更改 make_figure
的签名,使这些变量成为关键字参数,这样您就可以避免显式传递它们:
def make_figure(const_1=1, const_2=2, var_1=0.4, var_2=0.8):
....
interact(make_figure,
var_1=(0.2, 0.4, 0.05),
var_2=(0.75, 0.95, 0.05))
这是您可以尝试的 MCWE:
def calc_b(v1, v2):
return v1 + v2
def calc_c(v1, v2, v3):
return [v1, v2, v3]
def make_figure(const_1=1, const_2=2, var_1=0.4, var_2=0.8):
b = calc_b(var_1, var_2)
c = calc_c(b, const_1, const_2)
fig, ax = plt.subplots()
N, bins, patches = ax.hist(c)
interact(make_figure,
var_1=(0.2, 0.4, 0.05),
var_2=(0.75, 0.95, 0.05));
这运行没有任何错误。
你的addition 20160325
:
您传递给交互的每个参数都必须由以下之一表示(稍微简化一下):
- 一个滑块(对于
tuple
s,表示(最小值、最大值)和标量)
- 选择框(用于字符串和字典列表)
- 复选框(布尔值)
- 一个输入框(用于字符串)
您正在传递(通过在 get_marks
中将两个参数定义为 np.arrays
来隐含)。
所以 interact
不知道如何在滑块上表示它,因此出现错误。
您至少有两个选择:
1) 更改 get_marks
的签名,以便它采用 interact
无法理解的参数(参见上面的项目符号列表)
2) 创建另一个包装函数,它将采用 interact
无法理解的参数,但会调用 get_marks
在 将这些参数转换为任何 [=18] =] 需要。
只需多做一步,您就大功告成了。 ;-)
更新:
这是适合我的带有包装器的代码。
请注意,get_marks_interact
不需要采用 get_marks
的所有参数,并且我不传递列表,因为 interact
会对它们产生问题(列表应该代表字符串列表(对于下拉小部件)或 list/tuple 个 [min, max]
值(对于滑块))。
def get_marks(min_perc_four = 0.15,
min_perc_one = 0.85,
marks=marks_possible,
ach_per=ids_perc):
marks_real = marks # [0]
achieved_perc = ach_per # [0]
n_marks = marks_real.shape[0]
print("n_marks: ", n_marks)
n_students = achieved_perc.shape[0]
print("n_students: ", n_students)
# -----------------------------
# linear step between each mark
perc_necessary = get_perc_necessary(min_perc_one,
min_perc_four,
n_marks)
# test query: there need to be as many percentages as marks
if perc_necessary.shape[0] != marks_real.shape[0]:
print("the number of marks has to be equal the number of boundaries")
raise Exception
# ------------
# assign marks
final_marks = assign_marks(n_students,
perc_necessary,
achieved_perc,
marks_real)
# ------------
# create table
fig, ax = plt.subplots()
N, bins, patches = ax.hist(final_marks,
align='mid',
bins=np.sort(np.append(marks, 6.))) # bins=marks
ax.xaxis.set_major_formatter(FormatStrFormatter('%0.1f'))
bin_centers = 0.5 * np.diff(bins) + bins[:-1]
ax.set_xticks(bin_centers)
ax.set_xticklabels( marks )
ax.set_xlabel("mark")
ax.set_ylabel("number of marks")
ax.set_ylim(0.0, 6.0)
plt.grid(True)
def get_marks_interact(min_perc_four = 0.15,
min_perc_one = 0.85,):
return get_marks(min_perc_four, min_perc_one)
interact(get_marks_wrapper,
min_perc_four=(0.2, 0.4, 0.05),
min_perc_one=(0.75, 0.95, 0.05));
我想使用 matplotlib (1.5.1) 在 jupyter (4.0.6) notebook 中创建交互式绘图。问题是静态图是用一个有四个变量的函数创建的,其中两个是常量,两个是关键字参数,我想交互式地更改关键字参数。
这可能吗?如果可以,怎么做?
下面的概念代码显示了生成绘图的函数 make_figure(...)
和生成交互式绘图的命令。
如果我将关键字参数更改为变量,则会收到错误消息 "interact() takes from 0 to 1 positional arguments but 3 were given"
概念代码:
def make_figure(const_1, const_2, var_1=0.4, var_2=0.8):
b = calc_b(var_1, var_2)
c = calc_c(b, const_1, const_2)
fig, ax = plt.subplots()
N, bins, patches = ax.hist(c)
interact(make_figure,
const_1,
const_2,
var_1=(0.2, 0.4, 0.05),
var_2=(0.75, 0.95, 0.05))
补充20160325:代码示例
我正在尝试为 class 的分数创建直方图,具体取决于分别达到 1.0 和 4.0 所需的百分比。
# setup some marks
ids_perc = np.random.random(33)
print("number of entered marks: ", ids_perc.shape)
直方图的主要代码;主要功能:get_marks
# define possible marks
marks = np.array([1.0,
1.3,
1.7,
2.0,
2.3,
2.7,
3.0,
3.3,
3.7,
4.0,
5.0])
marks_possible = marks[::-1]
def get_perc_necessary(min_perc_one,
min_perc_four,
n_marks):
"""
calculates an equally spaced array for percentage necessary to get a mark
"""
delta = (min_perc_one - min_perc_four)/(n_marks-2-1)
perc_necessary_raw = np.linspace(start=min_perc_four,
stop=min_perc_one,
num=n_marks-1)
perc_necessary = np.append([0.0], np.round(perc_necessary_raw, decimals=2))
return perc_necessary
def assign_marks(n_students,
perc_necessary,
achieved_perc,
marks_real):
"""
get the mark for each student (with a certain achieved percentage)
"""
final_marks = np.empty(n_students)
for cur_i in range(n_students):
idx = np.argmax(np.argwhere(perc_necessary <= achieved_perc[cur_i]))
final_marks[cur_i] = marks_real[idx]
return final_marks
def get_marks(achieved_perc = ids_perc,
marks_real = marks_possible,
min_perc_four = 0.15,
min_perc_one = 0.85):
n_marks = marks.shape[0]
# print("n_marks: ", n_marks)
n_students = achieved_perc.shape[0]
# print("n_students: ", n_students)
# -----------------------------
# linear step between each mark
perc_necessary = get_perc_necessary(min_perc_one,
min_perc_four,
n_marks)
# test query: there need to be as many percentages as marks
if perc_necessary.shape[0] != marks_real.shape[0]:
print("the number of marks has to be equal the number of boundaries")
raise Exception
# ------------
# assign marks
final_marks = assign_marks(n_students,
perc_necessary,
achieved_perc,
marks_real)
# ------------
# create table
fig, ax = plt.subplots()
N, bins, patches = ax.hist(final_marks,
align='mid',
bins=np.append(marks,6.)) # bins=marks
ax.xaxis.set_major_formatter(FormatStrFormatter('%0.1f'))
bin_centers = 0.5 * np.diff(bins) + bins[:-1]
ax.set_xticks(bin_centers)
ax.set_xticklabels( marks )
ax.set_xlabel("mark")
ax.set_ylabel("number of marks")
ax.set_ylim(0.0, 6.0)
plt.grid(True)
现在,当我尝试设置 interact
时
interact(get_marks,
min_perc_four=(0.2, 0.4, 0.05),
min_perc_one=(0.75, 0.95, 0.05));
我收到错误
ValueError: array([ 0.22366653, 0.74206953, 0.47501716, 0.56536227, 0.54792759,
0.60288287, 0.68548973, 0.576935 , 0.84582243, 0.40709693,
0.78600622, 0.2692508 , 0.62524819, 0.62204851, 0.5421716 ,
0.71836192, 0.97194698, 0.4054752 , 0.2185643 , 0.11786751,
0.57947848, 0.88659768, 0.38803576, 0.66617254, 0.77663263,
0.94364543, 0.23021637, 0.30899724, 0.08695842, 0.50296694,
0.8164095 , 0.77892531, 0.5542163 ]) cannot be transformed to a Widget
为什么在查看变量 ids_perc
时出现此错误?
您需要在 interact()
中明确分配您的变量。例如,像这样:
const_1 = 1
interact(make_figure,
const_1=const_1,
const_2=2,
var_1=(0.2, 0.4, 0.05),
var_2=(0.75, 0.95, 0.05))
或者(如果可能)更改 make_figure
的签名,使这些变量成为关键字参数,这样您就可以避免显式传递它们:
def make_figure(const_1=1, const_2=2, var_1=0.4, var_2=0.8):
....
interact(make_figure,
var_1=(0.2, 0.4, 0.05),
var_2=(0.75, 0.95, 0.05))
这是您可以尝试的 MCWE:
def calc_b(v1, v2):
return v1 + v2
def calc_c(v1, v2, v3):
return [v1, v2, v3]
def make_figure(const_1=1, const_2=2, var_1=0.4, var_2=0.8):
b = calc_b(var_1, var_2)
c = calc_c(b, const_1, const_2)
fig, ax = plt.subplots()
N, bins, patches = ax.hist(c)
interact(make_figure,
var_1=(0.2, 0.4, 0.05),
var_2=(0.75, 0.95, 0.05));
这运行没有任何错误。
你的addition 20160325
:
您传递给交互的每个参数都必须由以下之一表示(稍微简化一下):
- 一个滑块(对于
tuple
s,表示(最小值、最大值)和标量) - 选择框(用于字符串和字典列表)
- 复选框(布尔值)
- 一个输入框(用于字符串)
您正在传递(通过在 get_marks
中将两个参数定义为 np.arrays
来隐含)。
所以 interact
不知道如何在滑块上表示它,因此出现错误。
您至少有两个选择:
1) 更改 get_marks
的签名,以便它采用 interact
无法理解的参数(参见上面的项目符号列表)
2) 创建另一个包装函数,它将采用 interact
无法理解的参数,但会调用 get_marks
在 将这些参数转换为任何 [=18] =] 需要。
只需多做一步,您就大功告成了。 ;-)
更新:
这是适合我的带有包装器的代码。
请注意,get_marks_interact
不需要采用 get_marks
的所有参数,并且我不传递列表,因为 interact
会对它们产生问题(列表应该代表字符串列表(对于下拉小部件)或 list/tuple 个 [min, max]
值(对于滑块))。
def get_marks(min_perc_four = 0.15,
min_perc_one = 0.85,
marks=marks_possible,
ach_per=ids_perc):
marks_real = marks # [0]
achieved_perc = ach_per # [0]
n_marks = marks_real.shape[0]
print("n_marks: ", n_marks)
n_students = achieved_perc.shape[0]
print("n_students: ", n_students)
# -----------------------------
# linear step between each mark
perc_necessary = get_perc_necessary(min_perc_one,
min_perc_four,
n_marks)
# test query: there need to be as many percentages as marks
if perc_necessary.shape[0] != marks_real.shape[0]:
print("the number of marks has to be equal the number of boundaries")
raise Exception
# ------------
# assign marks
final_marks = assign_marks(n_students,
perc_necessary,
achieved_perc,
marks_real)
# ------------
# create table
fig, ax = plt.subplots()
N, bins, patches = ax.hist(final_marks,
align='mid',
bins=np.sort(np.append(marks, 6.))) # bins=marks
ax.xaxis.set_major_formatter(FormatStrFormatter('%0.1f'))
bin_centers = 0.5 * np.diff(bins) + bins[:-1]
ax.set_xticks(bin_centers)
ax.set_xticklabels( marks )
ax.set_xlabel("mark")
ax.set_ylabel("number of marks")
ax.set_ylim(0.0, 6.0)
plt.grid(True)
def get_marks_interact(min_perc_four = 0.15,
min_perc_one = 0.85,):
return get_marks(min_perc_four, min_perc_one)
interact(get_marks_wrapper,
min_perc_four=(0.2, 0.4, 0.05),
min_perc_one=(0.75, 0.95, 0.05));