如何在Python中像在Matlab中一样使用数组

0 投票
1 回答
63 浏览
提问于 2025-04-14 16:50

我现在正在努力提升我的Python技能,想用它来重现一些我大学时做的老的Matlab项目。我曾经用Matlab模拟一个质子吸引电子,使用多维数组来存储每个时间点的位置和速度。现在我想在Python中做同样的事情,但数组的工作方式和Matlab大不相同。我遇到了很多错误,边试边学,但我觉得我还是在用“Matlab的思维”来看待数组,如果能给我一些在Python中实现这个的建议,我会非常感激。

#This code is for plotting the trajectory of an electron travelling through space
#The particle is in the vacinity of a central force (A proton at the origin)

import numpy as np
import matplotlib.pyplot as plt

re = np.array([[1e-11],[1e-11]]) #let re denote the trajectory of the electron with x = r[0] and y = r[1]
m = 9.11e-31 #mass of electron
k = 8.99e9 #Coulomb's constant [N m^2/C^2]
q = 1.6e-19 #charge of electron and proton [C]
rp = [0,0] #rp is the position of the proton
dt = 0.001 #time differential [s]

v = np.array([[-3e12],[0]]) #the electron has initial velocity of v = (-3, 0) [m/s]
phi = np.arctan2(re[1][0], re[0][0]) #starting angle

for i in range(1,10):
   # nrex = (re[0][i-1])+v[0][i-1]*dt #nuew position in x
   # nrey = (re[1][i-1])+v[1][i-1]*dt #new position in y
    re[0] = np.append(re[0], ((re[0][i-1])+v[1][i-1]*dt), axis=1) #, axis=1) #for each timestep move the velocity in x
    re[1] = np.append(re[1], ((re[1][i-1])+v[1][i-1]*dt), axis=1) #for each timestep mobe the velocity in y

    phi = np.arctan2(re[1][i],re[0][i]) #update the angle
    rho = np.sqrt(re[0][i]**2 + re[1][i]**2) #update separation from proton
    v[0] = np.append(n[0], (v[0][i-1]+((k*(q**2)/(rho**2))/m)*np.cos(phi)*dt), axis=1) #update velocity in x
    v[1] = np.append(v[1], (v[1][i-1]+((k*(q**2)/(rho**2))/m)*np.sin(phi)*dt), axis=1) #update velocity in y
    
plt.scatter(re[0][:], re[1][:], s=2, c='b') #Plot electron's trajectory
plt.scatter(rp[0],rp[1], s=3, c='r') #Show proton's position
plt.show() #Show

简单来说,我想做的是在数组的每个“向量”末尾添加系统的下一个“状态”(一个是位置,一个是速度,两个都包含x和y的分量),最后绘制每个时间状态,以查看整个轨迹。然而,这样做却返回了以下错误:

Traceback (most recent call last):
  File "c:\Users\hecto\OneDrive\Documentos\ITESM\8vo semestre\Repaso Python\ParticleInElectricField.py", line 20, in <module>    
    re[0] = np.append(re[0], ((re[0][i-1])+v[1][i-1]*dt), axis=1) #, axis=1) #for each timestep move the velocity in x
  File "<__array_function__ internals>", line 200, in append
  File "C:\Users\hecto\AppData\Local\Programs\Python\Python38\lib\site-packages\numpy\lib\function_base.py", line 5499, in append
    return concatenate((arr, values), axis=axis)
  File "<__array_function__ internals>", line 200, in concatenate
numpy.AxisError: axis 1 is out of bounds for array of dimension 1
PS C:\Users\hecto\OneDrive\Documentos\ITESM\8vo semestre\Repaso Python> 

难道不能在数组中的特定“向量”上添加内容吗?还是我漏掉了什么?任何指点都很有帮助,提前谢谢你!

当我尝试同样的代码,但去掉“axis=1”时,出现了关于数组维度的错误。这可能是因为没有这个参数,np.append会把向量压平。当我尝试“axis=0”时,错误变成了:

Traceback (most recent call last):
  File "c:\Users\hecto\OneDrive\Documentos\ITESM\8vo semestre\Repaso Python\ParticleInElectricField.py", line 20, in <module>
    re[0] = np.append(re[0], ((re[0][i-1])+v[1][i-1]*dt), axis=0) #, axis=1) #for each timestep move the velocity in x
  File "<__array_function__ internals>", line 200, in append
  File "C:\Users\hecto\AppData\Local\Programs\Python\Python38\lib\site-packages\numpy\lib\function_base.py", line 5499, in append        
    return concatenate((arr, values), axis=axis)
  File "<__array_function__ internals>", line 200, in concatenate
ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 1 dimension(s) and the array at index 
1 has 0 dimension(s)

这很奇怪,因为我想添加的是一个值,而不是一个数组。它的维度是0是有道理的,但为什么在添加到数组末尾时需要有维度呢?这让我觉得“axis=0”可能不是正确的方向,但我也说不出为什么。

1 个回答

0
re = np.array([[1e-11],[1e-11]])
....

v = np.array([[-3e12],[0]]) 
phi = np.arctan2(re[1][0], re[0][0]) 
for i in range(1,10):
   ....
    re[0] = np.append(re[0], ((re[0][i-1])+v[1][i-1]*dt), axis=1) #, axis=1) 
return concatenate((arr, values), axis=axis)
  File "<__array_function__ internals>", line 200, in concatenate
ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 1 dimension(s) and the array at index 
1 has 0 dimension(s)
re[0] = ...
...  
    phi = np.arctan2(re[1,i],re[0,i])
    rho = np.sqrt(re[0,i]**2 + re[1,i]**2)
re = np.zeros((10,2))   # or
re = np.zeros((2,10))   
relist = []
re[i,0 ] = new values
re[0,i] = ...
relist.append(new values)

re 一开始是一个 (2,1) 的数组。

另一个也是 (2,1) 的数组。

你可以用 re[1,0] 来索引。这种写法更常见。

你试图把一个形状为 (1,) 的东西和标量 re[0,i-1] 等进行连接。

如果用 axis=1,会报错 numpy.AxisError: axis 1 is out of bounds for array of dimension 1 (在 Python 中,索引是从 0 开始的,范围是 [0,n))。

如果用 axis=0,会报错:

注意,append 已经把操作转给了 concatenate。而 concatenate 要求所有输入的维度数量相同。你给它的是混合的 1d 和 0d。

它没有做到:

你不能通过赋值来“扩展”一个数组或数组的一行。MATLAB 允许这种扩展,内部会创建一个新的矩阵等。而 numpy 的数组不能“扩展”。concatenate 会创建一个新数组,并复制值。

因为你没有给 re 添加列,所以这个 i[i-1] 的索引没有任何实际意义。

要逐步做到这一点,可以先从

或者

然后在每一步你可以选择

或者

最后加上 re = np.array(relist)

Python 的列表是为了(相对)高效地增长而设计的;而数组则不是。

numpy 中,逐行遍历数组会更自然,因为后面的维度是最内层的(和 MATLAB 相反)。理论上两者都可以。


如果你需要将 (2,1) 的数组扩展到 (2,2),然后 (2,3) 等等,你需要用 axis=1 来 concatenate 一个 (2,1) 的数组。换句话说,就是把 (2,n) 和 (2,1) 连接起来,得到 (2,n+1)。

用列表的话,每一步简单地 append 一个包含 2 个元素的列表。最后你会得到一个列表的列表,这样就变成了一个 (n,2) 的数组,每一行对应一次迭代。

撰写回答