PythonNet中的Numpy重塑

0 投票
2 回答
33 浏览
提问于 2025-04-12 22:05

我正在用pythonnet在C#中使用numpy。我想改变一个数组的形状,但似乎不管怎么做都不行,我也搞不懂为什么。一开始我以为是复杂数组的问题,但后来我用整数试了一下,结果也是一样。

这是我的代码:

using System.Numerics;
using Python.Runtime;

static void Initialize()
{
    string pythonDll = @"C:\Users\Mohsen\AppData\Local\Programs\Python\Python39\python39.dll";
    Environment.SetEnvironmentVariable("PYTHONNET_PYDLL", pythonDll);
    PythonEngine.Initialize();    
}


Initialize();
Complex[] complexes = [
new Complex(1.0, 2.0),
new Complex(3.0, 4.0),
new Complex(5.0, 6.0),
new Complex(5.0, 6.0)

];
List<Complex> comlist = new List<Complex>(complexes);

using (Py.GIL())
{
    dynamic np = Py.Import("numpy");
    dynamic rawData = np.array(comlist);
    np.reshape(a: rawData.T, newshape:(2, 2), order:'F');
}

还有错误信息:

Unhandled exception. Python.Runtime.PythonException: expected sequence object with len >= 0 or a single integer
  File "C:\Users\Mohsen\AppData\Local\Programs\Python\Python39\lib\site-packages\numpy\core\fromnumeric.py", line 44, in _wrapit
    result = getattr(asarray(obj), method)(*args, **kwds)
  File "C:\Users\Mohsen\AppData\Local\Programs\Python\Python39\lib\site-packages\numpy\core\fromnumeric.py", line 67, in _wrapfunc
    return _wrapit(obj, method, *args, **kwds)
  File "C:\Users\Mohsen\AppData\Local\Programs\Python\Python39\lib\site-packages\numpy\core\fromnumeric.py", line 299, in reshape
    return _wrapfunc(a, 'reshape', newshape, order=order)
  File "<__array_function__ internals>", line 5, in reshape
   at Python.Runtime.PythonException.ThrowLastAsClrException()
   at Python.Runtime.PyObject.Invoke(PyTuple args, PyDict kw)
   at Python.Runtime.PyObject.InvokeMethod(String name, PyTuple args, PyDict kw)
   at Python.Runtime.PyObject.TryInvokeMember(InvokeMemberBinder binder, Object[] args, Object& result)
   at CallSite.Target(Closure, CallSite, Object, Object, ValueTuple`2, Char)
   at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid4[T0,T1,T2,T3](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
   at Program.<Main>$(String[] args) in C:\Users\Mohsen\RiderProjects\ConsoleApp2\ConsoleApp2\Program.cs:line 29

2 个回答

0

我觉得 numpy 需要的是数字的序列或者序列的序列来处理多维数组,而且它有自己专门的复数数据类型。你用 np.reshape(a: rawData.T, newshape:(2, 2), order:'F') 这种方式来改变数组的形状是对的,参数也没问题,不过 .T 是转置操作的简写。如果你只是想改变数组的形状,其实不一定要先转置。

我们需要把 Complex 对象转换成 numpy 能理解的格式。因为 numpy 有自己的复数类型,所以我们需要把你的 System.Numerics.Complex 数组转换成 numpy 可以处理的格式。一个简单的方法是把每个 Complex 对象转换成一个元组 (实部, 虚部),然后让 numpy 来处理这些元组。之后我们可以直接使用改变形状后的数组,或者把它赋值给一个变量。需要注意的是,numpy.reshape 不会直接修改原来的数组,而是会返回一个新的数组。

using System;
using System.Numerics;
using System.Collections.Generic;
using Python.Runtime;

static void Initialize()
{
    string pythonDll = @"C:\Users\Mohsen\AppData\Local\Programs\Python\Python39\python39.dll";
    Environment.SetEnvironmentVariable("PYTHONNET_PYDLL", pythonDll);
    PythonEngine.Initialize();
}

static void Main(string[] args)
{
    Initialize();

    Complex[] complexes = new Complex[]
    {
        new Complex(1.0, 2.0),
        new Complex(3.0, 4.0),
        new Complex(5.0, 6.0),
        new Complex(7.0, 8.0)
    };

    List<object> comlist = new List<object>();
    foreach (var complex in complexes)
    {
        comlist.Add(new PyTuple(new PyObject[] { new PyFloat(complex.Real), new PyFloat(complex.Imaginary) }));
    }

    using (Py.GIL()) // Python Global Interpreter Lock is acquired
    {
        dynamic np = Py.Import("numpy");
        dynamic rawData = np.array(comlist, dtype: np.complex);
        dynamic reshapedData = np.reshape(rawData, newshape: (2, 2), order: 'F');
        Console.WriteLine(reshapedData);
    }
}

希望这些对你有帮助。谢谢。

0

要让这个调整大小的功能正常工作,必须使用一个叫做PyTuple的对象。如果不是这样,它就无法正常运作,就是这么简单。

撰写回答