【问题标题】:Python indexing issue in while and for loopwhile 和 for 循环中的 Python 索引问题
【发布时间】:2016-12-16 10:47:56
【问题描述】:

我正在调整 Schorsch 在 While loop inside for loop in Matlab 中的回答,以便在 Python 3.5 中使用来解决我的问题。

我想遍历 t 数组中的值。对于每个值,如果我的计算结果z 收敛(或在最大迭代次数后不收敛)我将其复制到数组中。然后我绘制结果。

import numpy as np
import matplotlib.pyplot as plt

maxiter = 100 # max no. iterations in convergence loop
t = 0.05*np.arange(10)
z = 0.1 # initial guess
x = np.zeros(len(t)) # array for results
cvec = np.zeros(len(t)) # does loop converge?

for ii in t:

    print(ii)

    convergence = 0

    while convergence == 0:

        z_old = z
        z = ii*np.random.rand() # perform calculations

        # check convergence

        if abs(z-z_old) < 0.01: # convergence
            # store result
            convergence = 1
            x[ii] = z
            cvec[ii] = convergence

        elif abs(z-z_old) >= 0.01 and ii < maxiter: # no convergence but loop again
            convergence = 0
        else: # no convergence, move on to next value in t array
            convergence = 0
            x[ii] = 1e3
            cvec[ii] = convergence
            break

# plot result
plt.figure()
plt.plot(t[cvec==1],x[cvec==1],'x')
plt.xlabel('t')
plt.ylabel('x')
plt.show()

我收到一个错误:VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future lines = """

这是否意味着我必须更改索引whilefor 循环的方式,如果是,我应该怎么做?

【问题讨论】:

  • 这可能意味着您正在使用x[ii] 索引数组,而ii 不是整数。您的 t 数组(用于迭代 for 循环的数组)有问题。如果它是整数数组,但不知何故是浮点数,你可以做类似for ii in np.asarray(t, np.int32).
  • 您的问题标题具有误导性。
  • 为什么要使用浮点值进行索引?我建议在循环之前将xcvec 设置为一个空列表,然后根据需要附加值,即x.append(z)。或者,您可以使用计数器来索引xcvec,然后在每次设置元素时将其递增。如果您还需要存储时间,只需设置timestamps = [] 之类的内容并附加到它上面。
  • @pbreach 如果我有一个包含 1000 个元素的 t 数组,那么使用 append 函数或从我的 MWE 中的零数组开始会更有效吗?
  • 实际上,现在我认为最简单的方法是使用for idx, ii in enumerate(t):,然后使用idx 进行索引,无需计数器或切换到列表:)。在我没有意识到您在不收敛的情况下存储x 的值之前。有关enumerate 功能,请参阅here

标签: python arrays numpy for-loop while-loop


【解决方案1】:

问题与x[ii] =cvec[ii] 行有关。当您尝试访问非整数索引时。 这些索引是在以下行生成的:

(...)
t = 0.05*np.arange(10) #[ 0.  ,  0.05,  0.1 ,  0.15,  0.2 ,  0.25,  0.3 ,  0.35,  0.4 ,  0.45]
(...)

要解决此问题,有多种方法可以解决,但最简单的方法是访问与 t 变量中的值相同的索引。

import numpy as np
import matplotlib.pyplot as plt

maxiter = 100 # max no. iterations in convergence loop
t = 0.05*np.arange(10)
z = 0.1 # initial guess
x = np.zeros(len(t)) # array for results
cvec = np.zeros(len(t)) # does loop converge?

for idx, ii in enumerate(t):

    print(ii)

    convergence = 0

    while convergence == 0:

        z_old = z
        z = ii*np.random.rand() # perform calculations

        # check convergence

        if abs(z-z_old) < 0.01: # convergence
            # store result
            convergence = 1
            x[idx] = z
            cvec[idx] = convergence

        elif abs(z-z_old) >= 0.01 and ii < maxiter: # no convergence but loop again
            convergence = 0
        else: # no convergence, move on to next value in t array
            convergence = 0
            x[idx] = 1e3
            cvec[idx] = convergence
            break

# plot result
plt.figure()
plt.plot(t[cvec==1],x[cvec==1],'x')
plt.xlabel('t')
plt.ylabel('x')
plt.show()

使用while循环迭代一个值的最大次数,而它不收敛

import numpy as np
import matplotlib.pyplot as plt

maxiter = 100 # max no. iterations in convergence loop
t = 0.05*np.arange(10)
z = 0.1 # initial guess
x = np.zeros(len(t)) # array for results
cvec = np.zeros(len(t)) # does loop converge?

for idx, ii in enumerate(t):

    print(ii)

    # Assume it wont converge
    # So if we loop through all the max iterations and still no convergence, it is already marked
    x[idx] = 1e3
    cvec[idx] = 0

    while iter in range(maxiter):

        z_old = z
        z = ii*np.random.rand() # perform calculations

        if abs(z-z_old) < 0.01: # converge, therefore stop looping
            x[idx] = z
            cvec[idx] = 1
            break

# plot result
plt.figure()
plt.plot(t[cvec==1],x[cvec==1],'x')
plt.xlabel('t')
plt.ylabel('x')
plt.show()

【讨论】:

  • 感谢@AdrianoMartins。我认为应该有一个while循环计数器(tutorialspoint.com/python/python_while_loop.htm)。对于elif abs(z-z_old) &gt;= 0.01 and ii &lt; maxiter: # no convergence but loop again 行,我们使用链接中的示例符号将ii 更改为counter
  • 更新了答案。如果我设法理解正确,那么新代码应该可以满足您的期望
  • 好的,谢谢 - 第二个代码块中的 break 命令是否意味着不缩进?
  • 对不起。我误解了这个问题 - 并做了一些错别字。修复。现在它应该循环直到收敛,或者如果达到最大迭代次数则放弃。
猜你喜欢
  • 2022-01-22
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-02
  • 2018-11-05
  • 2022-06-28
相关资源
最近更新 更多