如何矢量化数组重新格式化?

时间:2015-05-11 14:46:34

标签: matlab

我有一个.csv文件,其中每行的数据格式为(x,y,z,t,f),其中f(x,y,z)位置t处某个函数的值(x,y,z,t)。因此,.csv中的每个新行都会提供一组新的坐标f,并附带值imagesc。 .csv没有排序。

我希望随着时间的推移,使用xyimagesc - 平面中创建此数据的视频。我这样做的方法是将M重新格式化为M = csvread('file.csv'); uniqueX = unique(M(:,1)); uniqueY = unique(M(:,2)); uniqueT = unique(M(:,4)); M_reformatted = zeros(length(uniqueX), length(uniqueY), length(uniqueT)); for i = 1:length(uniqueX) for j = 1:length(uniqueY) for k = 1:length(uniqueT) M_reformatted(i,j,k) = M( ... M(:,1)==uniqueX(i) & ... M(:,2)==uniqueY(j) & ... M(:,4)==uniqueT(k), ... 5 ... ); end end end 更容易使用的内容。我正在做三个嵌套循环,大致类似于

M_reformatted

我有k后,我可以循环执行时间步imagesc并在M_reformatted(:,:,k)上使用//******************************/ // Aiming Controls //******************************/ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Left)) { float sin = sinf(-m_fRotationSpeed*elapsedTime); float cos = cosf(-m_fRotationSpeed*elapsedTime); sf::Vector2f newDirection; newDirection.x = (cos*m_vAimDirection.x) - (sin * m_vAimDirection.y); newDirection.y = (sin*m_vAimDirection.x) + (cos*m_vAimDirection.y); //Update sprite rotation // Find angle of rotation by acos(v1dotv2) float rotationAngle = acosf(1 * m_vAimDirection.y); // Check to make sure we get the right direction! if (m_vAimDirection.x < 0) rotationAngle = (b2_pi*2.0f) - rotationAngle; // convert to degrees rotationAngle *= 180.0f / b2_pi; // HERE IS WHERE I CHECK THE BOUNDS if (rotationAngle > 88.0f && rotationAngle < 272.0f) rotationAngle = 88.0f; else m_vAimDirection = newDirection; //apply new rotation m_sCannon.setRotation(rotationAngle); } else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Right)) { float sin = sinf(m_fRotationSpeed*elapsedTime); float cos = cosf(m_fRotationSpeed*elapsedTime); sf::Vector2f newDirection; newDirection.x = (cos*m_vAimDirection.x) - (sin * m_vAimDirection.y); newDirection.y = (sin*m_vAimDirection.x) + (cos*m_vAimDirection.y); //Update sprite rotation // Find angle of rotation by acos(v1dotv2) float rotationAngle = acosf(1 * m_vAimDirection.y); // Check to make sure we get the right direction! if (m_vAimDirection.x < 0) rotationAngle = (b2_pi*2.0f) - rotationAngle; // convert to degrees rotationAngle *= 180.0f / b2_pi; // HERE IS WHERE I CHECK THE BOUNDS if (rotationAngle < 272.0f && rotationAngle > 88.0f) rotationAngle = 272.0f; else m_vAimDirection = newDirection; //apply new rotation m_sCannon.setRotation(rotationAngle); } 。但是执行上面的嵌套循环非常慢。是否可以对上述进行矢量化?如果是这样,该方法的大纲将非常有用。

编辑:如下面的答案/评论中所述,我犯了一个错误,因为有几个可能的z值,我没有考虑到。如果只有一个z值,上面就可以了。

2 个答案:

答案 0 :(得分:3)

我认为你不需要矢量化。我想你改变了你的算法。

您只需要一个循环来逐步浏览CSV文件的行。对于每一行,您都有(x,y,z,t,f),因此只需将其存储在M_reformatted所属的位置即可。像这样:

M_reformatted = zeros(max(M(:,1)), max(M(:,2)), max(M(:,4)));
for line = 1:size(M,2)
    z = M(line, 3);
    if z ~= 0, continue; end;
    x = M(line, 1);
    y = M(line, 2);
    t = M(line, 4);
    f = M(line, 5);
    M_reformatted(x, y, t) = f;
end

另请注意,预分配M_reformatted是一个非常好的主意,但您的代码可能已经错误(取决于数据)。我认为像我一样使用max将会做正确的事。

答案 1 :(得分:3)

此向量化解决方案允许xy的负值,并且比非向量化解决方案快许多倍(对于底部的测试用例,接近20倍)。

我们的想法是使用x按字典顺序对ytsortrows值进行排序,然后使用reshape构建时间片M_reformatted

代码:

idx = find(M(:,3)==0);            %// find rows where z==0
M2 = M(idx,:);                    %// M2 has only the rows where z==0
M2(:,3) = [];                     %// delete z coordinate in M2
M2(:,[1 2 3]) = M2(:,[3 1 2]);    %// change from (x,y,t,f) to (t,x,y,f)

M2 = sortrows(M2);                 %// sort rows by t, then x, then y

numT = numel(unique(M2(:,1)));     %// number of unique t values
numX = numel(unique(M2(:,2)));     %// number of unique x values
numY = numel(unique(M2(:,3)));     %// number of unique y values

%// fill the time slice matrix with data
M_reformatted = reshape(M2(:,4), numY, numX, numT);

注意:我假设y指的是图片的,而x指的是。如果您希望这些翻转,请在代码末尾使用M_reformatted = permute(M_reformatted,[2 1 3])

我用于M的测试用例(将结果与其他解决方案进行比较)的NxNxN空间为T次切片:

N = 10;
T = 10;

[x,y,z]     = meshgrid(-N:N,-N:N,-N:N);
numPoints   = numel(x);
x=x(:); y=y(:); z=z(:);
s = repmat([x,y,z],T,1);
t = repmat(1:T,numPoints,1);
M = [s, t(:), rand(numPoints*T,1)];
M = M( randperm(size(M,1)), : );