我有一个具有309.760个元素的&[f64]
。这个数据集是一个包含7040个属性集的数组。每个属性集包含一对f64
s和14个f64
三元组。
我只对三胞胎感兴趣。
我可以像这样读取这个数据集到narray中:
let array = Array::from_iter(data);
let mut propertysets = vector.into_shape(IxDyn(&[7040, 44])).unwrap();
,我可以像这样删除每个属性集的前两个f64
:
propertysets.remove_index(Axis(1), 0);
propertysets.remove_index(Axis(1), 0);
println!("{:?}", propertysets.shape()); // [7040, 42]
看起来很有希望。但现在我想重塑数组为[7040,14,3],这应该工作,因为3 * 14 = 42
,但:
let result = propertysets.into_shape(IxDyn(&[7040, 14, 3])).unwrap();
对这条消息感到恐慌:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ShapeError/IncompatibleLayout: incompatible memory layout'
remove_index的文档说:
元素不会被取消初始化或删除,只是被移出视图
这可能解释了为什么这个失败。但是怎样才能做到呢?我是否必须以某种方式复制propertysets
到正确形状的新数组中?但如何?
使用Array::from_iter(propertysets.iter())
将导致&f64
而不是f64
的narray。
要使into_shape操作生效,数组必须在内存中是c-连续的或fortrans -连续的(参见文档)。在
vector.into_shape(IxDyn(&[7040, 44])).unwrap();
它们是连续的。但在
propertysets.remove_index(Axis(1), 0);
它们不是。为什么?整个数组不会被remove_index
移动。元素被移出视图(参见文档)。
如何解决?
- 使用
from_shape_vec
重组 - 使用新的
to_shape
函数。(不是文档,但这里有一些信息和大量的例子在这里)
例子:
use ndarray::{Array, Order, ViewRepr};
use ndarray::IxDyn;
use ndarray::Axis;
use ndarray::ArrayBase;
use ndarray::CowRepr;
use ndarray::Dim;
use ndarray::OwnedRepr;
fn into_shape_reassemble(data: Vec<f64>) -> Array<f64, IxDyn>
{
let array = Array::from_iter(data);
let mut result = array.into_shape(IxDyn(&[7040, 44])).unwrap();
result.remove_index(Axis(1), 0);
result.remove_index(Axis(1), 0);
let result = Array::from_shape_vec((7040, 42), result.iter().cloned().collect()).unwrap();
let result = result.into_shape(IxDyn(&[7040, 14, 3])).unwrap();
println!("{:?}", result.shape());
result
}
fn to_shape(data: Vec<f64>) -> ArrayBase<OwnedRepr<f64>, IxDyn>
{
let array = Array::from_iter(data);
let mut result = array.into_shape(IxDyn(&[7040, 44])).unwrap();
result.remove_index(Axis(1), 0);
result.remove_index(Axis(1), 0);
let result = result.to_shape((7040, 14, 3)).unwrap().to_owned();
println!("{:?}", result.shape());
result.into_dyn()
}
#[cfg(test)]
mod tests {
#[test]
fn test_into_shape() {
let data = vec![0.; 7040 * 44];
super::into_shape_reassemble(data);
}
#[test]
fn test_to_shape() {
let data = vec![0.; 7040 * 44];
super::to_shape(data);
}
}
输出:
[7040, 14, 3]
[7040, 14, 3]