我在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
我在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()
我收到错误:
line 23, in segment_energy
indicator[above] = 1
IndexError: too many indices for array
data
是从包含三轴加速度计数据的CSV文件中读取的pandas DataFrame
。加速度计数据的轴为x
,y
和z
。数据框的列按此顺序为timestamp
,time skipped
,x
,y
,z
和label
。
错误是因为Python代码中的mag
是标量,我将其视为矩阵。但是,我不确定他们如何将mag
转换为MATLAB函数中的矩阵。
答案 0 :(得分:3)
默认情况下,numpy.linalg.norm
的输出会给出一个标量值,给出您当前调用该函数的方式。因为mag
的输出现在是标量,所以其余代码将无法按预期运行,原因如下:
使用单个标量执行平均减法将得到值0(即mag <- mag - np.mean(mag) --> 0
)。
above
语句将始终返回单个元素的元组。该元素包含一个长度为1的NumPy数组,其中包含索引0,表示“array”的第一个元素(在这种情况下是标量)满足约束条件。通过使用np.std
的默认定义,单个常量的标准偏差也为0,这一点始终得到满足。
调用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
最后,调用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
因此,您的解决方案是重新考虑如何编写此功能。 MATLAB代码假定data
已经是一个2D矩阵,因此他们独立地计算每行的范数或长度。因为我们现在知道输入是一个pandas DataFrame
,所以我们可以很容易地在它上面应用numpy
操作,就像在MATLAB中做的那样。假设您的列在代码中标记为x
,y
和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()
代码中的第一个语句是MATLAB中代码的实际NumPy转换。我们使用pandas loc
的一部分DataFrame
方法来索引您要查找的三个列。我们还需要转换为NumPy数组,以便其余的计算工作。
您也可以使用numpy.linalg.norm
,但指定要操作的轴。由于数据是2D,请指定axis=1
以计算矩阵的行方式:
mag = np.linalg.norm(data.loc[:, ['x', 'y', 'z']], axis=1)
以上内容会将数据合并为NumPy数组。