Как создать 3d ndarray из 1d ndarray

Я хотел бы создать 3d-ndarray для представления координат из трех 1d-ndarray, аналогично тому, как работает сетка numpy. например каков эквивалент ржавчины для Python:

a = np.array(
    np.meshgrid(
        np.linspace(-1, 1, 50),
        np.linspace(-1, 1, 50),
        np.linspace(-1, 1, 50),
        indexing = "ij"
    )
)
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
0
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хотя он не встроен, мы можем написать свой собственный. Несмотря на то, что он кажется универсальным для всех измерений, он будет работать только с 5 входными массивами, поскольку Dim<[Ix; 6]> — это наибольшая размерность, реализующая Dimension. (Помимо этого нам нужно будет выделить динамические массивы и/или использовать IxDyn.)

use ndarray::{prelude::*, Data, Ix, OwnedRepr, RawData};
use num_traits::Zero;

enum Indexing {
    Ij,
    Xy,
}

fn meshgrid<S, const N: usize>(
    arrs: [ArrayBase<S, Ix1>; N],
    indexing: Indexing,
) -> ArrayBase<
    OwnedRepr<<S as RawData>::Elem>,
    <Dim<[Ix; N]> as Dimension>::Larger,
>
where
    S: Data + RawData + Clone,
    <S as ndarray::RawData>::Elem: Clone,
    Dim<[Ix; N]>: Dimension,
    <Dim<[Ix; N]> as Dimension>::Larger: Dimension + Zero,
{
    let mut out_shape = <Dim<[Ix; N]> as Dimension>::Larger::zero();
    for (i, dim) in out_shape.as_array_view_mut().iter_mut().enumerate() {
        *dim = if i == 0 { N } else { arrs[i - 1].len() };
    }

    let mut out_arrs = Array::uninit(out_shape);

    for (i, (mut out_arr, in_arr)) in
        out_arrs.outer_iter_mut().zip(&arrs).enumerate()
    {
        for lane in out_arr.view_mut().lanes_mut(Axis(i)) {
            in_arr.assign_to(lane);
        }
    }

    if matches!(indexing, Indexing::Xy) && N > 1 {
        out_arrs.swap_axes(N - 1, N - 2);
    }

    unsafe { out_arrs.assume_init() }
}

fn main() {
    let arr1 = Array1::linspace(-1.0, 1.0, 2);
    let arr2 = Array1::linspace(-1.0, 1.0, 3);
    let arr3 = Array1::linspace(-1.0, 1.0, 4);
    let grid = meshgrid([arr1, arr2, arr3], Indexing::Ij);

    println!("{grid:?}");
}
[[[[-1.0, -1.0, -1.0, -1.0],
   [-1.0, -1.0, -1.0, -1.0],
   [-1.0, -1.0, -1.0, -1.0]],

  [[1.0, 1.0, 1.0, 1.0],
   [1.0, 1.0, 1.0, 1.0],
   [1.0, 1.0, 1.0, 1.0]]],


 [[[-1.0, -1.0, -1.0, -1.0],
   [0.0, 0.0, 0.0, 0.0],
   [1.0, 1.0, 1.0, 1.0]],

  [[-1.0, -1.0, -1.0, -1.0],
   [0.0, 0.0, 0.0, 0.0],
   [1.0, 1.0, 1.0, 1.0]]],


 [[[-1.0, -0.33333333333333337, 0.33333333333333326, 1.0],
   [-1.0, -0.33333333333333337, 0.33333333333333326, 1.0],
   [-1.0, -0.33333333333333337, 0.33333333333333326, 1.0]],

  [[-1.0, -0.33333333333333337, 0.33333333333333326, 1.0],
   [-1.0, -0.33333333333333337, 0.33333333333333326, 1.0],
   [-1.0, -0.33333333333333337, 0.33333333333333326, 1.0]]]], shape=[3, 2, 3, 4], strides=[24, 12, 4, 1], layout=Cc (0x5), const ndim=4

Спасибо, есть идеи, почему этого еще нет в ndarray? кажется странной вещью, которую стоит опустить, учитывая, насколько популярен meshgrid для numpy и что (хотя ваше решение значительно более элегантно, чем то, что я мог бы придумать) реализовать его не кажется очень сложной вещью. P.S. если вы еще не сделали/не планируете делать запрос на включение этой функции в ndarray, вы не возражаете, если я это сделаю (я, конечно, отдам вам должное и дам ссылку на этот вопрос)?

Pioneer_11 13.07.2024 18:08

Меня не волнует кредит. Не стесняйтесь сделать этот пиар самостоятельно.

BallpointBen 14.07.2024 04:20

Я провел еще немного тестирования и обнаружил, что ваша функция сетки повторяет выходные данные столько же раз, сколько и измерений. Например. meshgrid для 3d выводит массив 4d, содержащий три идентичных массива 3d, например:

Pioneer_11 28.07.2024 21:45
let n = 3; let max = 1.0; let min = -1.0; let grid = meshgrid( [ nd::Array::linspace(min, max, n), nd::Array::linspace(min, max, n), nd::Array::zeros(n), ], Indexing::Ij ); println!("{:#?}", grid.slice(nd::s![.., .., .., 0])); println!("==================================================‌​======= = "); println!("{:#?}", grid.slice(nd::s![.., .., .., 1])); println!("==================================================‌​======= = "); println!("{:#?}", grid.slice(nd::s![.., .., .., 2]));
Pioneer_11 28.07.2024 21:46

Не могли бы вы сообщить мне, как я могу это исправить? Я ожидаю, что это относится к этой строке: let mut out_shape = <Dim<[Ix; N]> as Dimension>::Larger::zero(); но, честно говоря, я не так хорошо знаком с чертами ndarray, как вы

Pioneer_11 28.07.2024 21:47

Другие вопросы по теме