如何将矩阵从Matlab转换为Python?

dir*_*s45 6 python matlab numpy matrix pandas

我在Matlab中有以下代码,我不熟悉:

function segments = segmentEnergy(data, th)
    mag = sqrt(sum(data(:, 1:3) .^ 2, 2));
    mag = mag - mean(mag);

    above = find(mag>=th*std(mag));
    indicator = zeros(size(mag));
    indicator(above) = 1;
    plot(mag); hold on; plot(indicator*1000, 'r')
end
Run Code Online (Sandbox Code Playgroud)

我在Python中编写了以下函数:

def segment_energy(data, th):
    mag = np.linalg.norm((data['x'], data['y'], data['z']))
    print "This is the mag: " + str(mag)
    mag -= np.mean(mag)

    above = np.where(mag >= th * np.std(mag))
    indicator = np.zeros(mag.shape)
    indicator[above] = 1
    plt.plot(mag)
    plt.plot(indicator * 1000, 'r')
    plt.show()
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:

line 23, in segment_energy
indicator[above] = 1
IndexError: too many indices for array
Run Code Online (Sandbox Code Playgroud)

dataDataFrame从包含三轴加速度计数据的CSV文件中读取的大熊猫.加速度计数据的轴x,yz.用于数据帧的列是timestamp,time skipped,x,y,z,和label以该顺序.

错误是因为mag在Python代码中是标量,我将其视为矩阵.但是,我不确定它们是如何mag在MATLAB函数中变成矩阵的.

ray*_*ica 2

默认情况下,给出的输出numpy.linalg.norm将为您提供一个标量值,给出您当前调用该函数的方式。由于 的输出mag现在是标量,因此其余代码将无法按预期运行,原因如下:

  1. 使用单个标量执行均值减法将得到 0 值(即mag <- mag - np.mean(mag) --> 0)。

  2. above语句将始终返回单个元素的元组。该元素包含一个长度为 1 的 NumPy 数组,其中包含索引 0,表示“数组”的第一个元素(在本例中是标量)满足约束。这始终可以满足,因为通过使用 的默认定义,单个常量的标准差也为 0 np.std

  3. 调用shape单个标量值是未定义的,它实际上会给您一个空形状:()。请注意,如果您没有使用 进行减法numpy.mean,那么mag.shape实际上会给您带来错误,因为它不是 NumPy 数组。相减将np.mean标量合并为 NumPy 数组。

    观察:

    In [56]: mag = 10
    
    In [57]: type(mag)
    Out[57]: int
    
    In [58]: mag -= np.mean(mag)
    
    In [59]: type(mag)
    Out[59]: numpy.float64
    
    Run Code Online (Sandbox Code Playgroud)
  4. 最后,调用indicator创建代码将生成一个空维度的数组,并且由于您尝试索引到一个没有大小的数组,因此会出现错误。

观察这个可重现的错误,假设mag计算出的值是某个值......比如说...... 10 和th = 1

In [60]: mag = 10

In [61]: mag -= np.mean(mag)

In [62]: mag.shape
Out[62]: ()

In [63]: th = 1

In [64]: above = np.where(mag >= th * np.std(mag))

In [65]: indicator = np.zeros(mag.shape)

In [66]: indicator
Out[66]: array(0.0)

In [67]: mag
Out[67]: 0.0

In [68]: indicator[above] = 1
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-67-adf9cff7610a> in <module>()
----> 1 indicator[above] = 1

IndexError: too many indices for array
Run Code Online (Sandbox Code Playgroud)

因此,您的解决方案是重新考虑如何编写此函数。MATLAB 代码假设data已经是一个二维矩阵,因此它们独立计算每行的范数或长度。因为我们现在知道输入是 pandas DataFrame,所以我们可以非常轻松地numpy对其应用操作,就像在 MATLAB 中所做的那样。假设您的列被标记为xy并且z在您的代码中,每列都是一个numpy值数组,只需更改第一行代码即可。

def segment_energy(data, th):
    mag = np.sqrt(np.sum(data.loc[:, ['x','y','z']]** 2.0, axis=1)) # Change
    mag = np.array(mag) # Convert to NumPy array
    mag -= np.mean(mag)

    above = np.where(mag >= th * np.std(mag))
    indicator = np.zeros(mag.shape)
    indicator[above] = 1
    plt.plot(mag)
    plt.plot(indicator * 1000, 'r')
    plt.show()
Run Code Online (Sandbox Code Playgroud)

代码中的第一条语句是 MATLAB 中代码的实际 NumPy 翻译。我们使用locpandas 的方法DataFrame来索引您要查找的三列。我们还需要转换为 NumPy 数组才能进行其余的计算。

您也可以使用numpy.linalg.norm,但指定要操作的轴。由于数据是二维的,因此指定axis=1计算矩阵的行范数:

mag = np.linalg.norm(data.loc[:, ['x', 'y', 'z']], axis=1)
Run Code Online (Sandbox Code Playgroud)

上面的代码会将数据合并到 NumPy 数组中。