- 已关闭**。此问题需要details or clarity。当前不接受答案。
- 想要改进此问题?**添加详细信息并通过editing this post阐明问题。
5小时前关门了。
Improve this question
我想在python中画一个方波,但是我不能这样做,因为我不能检查f函数中x的值:
import matplotlib.pyplot as plt
import numpy as np
import math
I = float(input())
t = float(input())
T = float(input())
def f(x):
if x % T <= (T / 2):
return I
else:
return -I
x = np.linspace(0, t, 1000)
plt.plot(x, f(x))
plt.xlim(0, t)
plt.ylim(-10, 10)
plt.axhline(color="black")
plt.show()
我怎么能这么做呢?
2条答案
按热度按时间b4lqfgs41#
我猜您正在寻找
numpy.where
:a5g8bdjr2#
你的问题是,你在整个数组
x
上应用f
,一般来说这是个好主意,因为numpy的关键就是通过这样做来加速计算(python是一种非常慢的语言,但是numpy不是用python写的,所以numpy能为你做的每一批计算都快得多)。因此,您在这里体验到的是numpy的广播和矢量化功能:一段代码,
f
,很明显,你写的时候考虑到了标量,几乎可以把参数x
作为一个数组来使用。x%T
是一个数组,其每个元素都是x[i]%T
,其中i在range(len(x))
中。x%T<=T/2
是一个布尔数组,其每个元素为真或假,具体取决于是否为x[i]%T<=T/2
。然后它就停止工作了,因为你可以用一个布尔数组作为
if
的条件,if
的条件必须是一个truth
值:要么是真,要么不是。你得到的是一个数组,一些是真,一些是假。因此你得到了错误:现在您有3个解决方案,从最简单的到需要最多调整的,但也从最慢的到最快的。
1.您可以直接在标量上调用
f
,因此构建一个数组y
(如y[i]=f(x[i])
)并将其传递给plot
你的
f
函数,按原样,运行良好。只是调用出错了。它是用标量调用的,你用vector调用了它。用这个for循环,我更正了一下,用标量调用了它(n次)。1.你可以让numpy用所谓的
vectorize
函数来做这件事。vectorize将一个要在标量(或其他对象,但我感兴趣的是这种情况)上调用的函数转换为可以用任何形状的数组调用的函数,然后返回一个相同形状的数组,其所有元素都是
f(z)
,因为z
是x
的任何元素所以在你的情况下
但这是一个错误的好主意。所有这些它都和我的第一个版本一样,但它为你做了for循环。
尽管如此,它仍然更快。而且仍然相当容易编写(至少在这样一个规范的情况下。使用
vectorize
有时可能是相当大的挑战)。1.向量化
但大多数情况下,你也不例外,你可以自己对函数进行向量化,也就是说,重写
f
来处理一个标量向量,而不是一个标量向量,我们在序言中已经看到,一半的工作已经完成了:你已经计算了一个布尔数组,告诉你返回元素应该是I
还是-I
。例如
x%T<=T/2
是我们之前提到的布尔数组,np.where
返回一个相同形状的数组,整数值取自第二个或第三个参数。另一种在数学中更常见的方法是
(基于numpy中,用于算术运算的布尔值为0或1这一事实)
时间
在我的计算机上,第一个解决方案(使用for循环)每次运行需要308毫秒。
第二个(使用向量化),每次运行159毫秒,所以快了两倍,因为for循环是用numpy而不是python完成的,但是,for循环中的代码仍然是python代码。
第三个(
np.where
或算术版本)每次运行需要13 ms。所以,你看,它不是一个真正的选项。你需要使用第三个选项。一般来说,当使用numpy时,你必须不惜一切代价避免for循环,并尽量把每个操作看作是对数组的操作,而不是对数组中的元素的操作。我提供了3个选项来帮助你理解发生了什么,以及需要做什么。但实际上,只有这3个解是有效的(即使你不关心计算时间,最好在使用numpy时就开始这样想)