以下Python代码将重复将向量[1, 2, 3, 4]
添加到二维数组a
中的每一行,仅从第20行开始。
import numpy as np
# an array of shape (100, 4)
a = np.zeros((100, 4), dtype=np.float32)
# and this is the operation explained above
a[20:, :] += [1.0, 2.0, 3.0, 0.0]
与ndarray
有一个简单的等价物吗?
我已经可以用更复杂的杂乱外观代码做我需要的东西,但觉得可能有一个整洁的ndarray.rs等效。
好的,冒着让问题过于复杂的风险,我认为可能有一个简单的答案,我无法发现......
我使用的f32形状(n,8)数组代表三个顶点位置,三个正常分量和两个纹理贴图坐标。我正在将多个3D对象的缓冲区合并为一个,以实现更高效的图形渲染。在8个宽阵列中,前三个值需要缩放,即乘以&[sx, sy, sz]
,然后使用标准rz.dot(&rx.dot(&ry.dot()))
函数旋转,最后添加位移&[dx, dy, dz]
。法线只需旋转即可。我当前的系统涉及将数据保存在中间数组变量中。
use ndarray as nd;
array_buffer: nd::Array2<f32>, loc: &[f32; 3], scl: &[f32; 3]...
...
// scale then rotate new verts then add displacement
let new_verts = &new_buf.array_buffer.slice(s![.., 0..3]) * &nd::arr1(scl);
let new_verts = rotate_vec(rot, &new_verts) + &nd::arr1(loc);
// then add them to existing verts
let mut verts = nd::stack(nd::Axis(0),
&[old_buf.array_buffer.slice(s![.., 0..3]),
new_verts.view()]).unwrap();
...
我知道我无法将它减少到numpy one liner
verts = np.append(old_buf.array_buffer[:,0:3],
rotate_vec(rot, (new_buf.array_buffer[:,0:3] * scl) + loc))
但我认为也许某些地图或zip变体或宏可能对我有所帮助。
答案 0 :(得分:10)
可以使用与在Python中执行的步骤相同的两个步骤来完成:slicing,然后添加分配到broadcast右手数组。
use ndarray::Array2;
let mut a: Array2<f32> = Array2::zeros((100, 4));
{
let mut slice = a.slice_mut(s![20.., ..]);
slice += &ArrayView::from(&[1.0, 2.0, 3.0, 4.0]);
}
使用slice_mut
和s!
宏完成切片以定义预期范围。
切片的结果是一个可变数组视图,因此,ArrayBase
中看到的大多数操作都可用,包括算术运算。
通过广播规则,右侧的形状[4]
数组可以自动广播到[100, 4]
运算符的形状+=
之一。
如果从Python到Rust的ndarray
包转换中存在其他混淆,则文档包含guide for Python users。