通过JPype和numpy进行Java类型转换到Python

6

我目前正在将一个用Python编写的程序移植到Java,并遇到了一些问题。我一次移植程序的一部分,为了测试目的,我正在使用JPype使其兼容新的Java类。

编辑:为了更清楚地说明,我目前正在处理的类为整个Python程序提供数据。

因此,在我的Java类中,我有一些存储在ArrayList中的float和byte值,

    ArrayList<ArrayList<Float>> dataFloat  = new ArrayList<ArrayList<Float>>();
    ArrayList<ArrayList<Byte>>  dataByte   = new ArrayList<ArrayList<Byte>>();

然后通过使用JPype,我可以将这些内容传输到我的Python环境中,现在它的类型为

    <class 'jpype._jclass.java.util.ArrayList'> .

现在我想在Python中将它们简单地转换为numpy数组。

    numpy.array(dataFloat) .

一开始看起来好像行得通,印出来看着不错,


    [[1.0 2.0 3.0]
    [80.0 127.0 127.0]
    [255.0 255.0 255.0]] .

然而,由于程序要求数值为浮点型,这并不能与程序的其余部分兼容。经过进一步研究,我发现我所拥有的这些“浮点数”实际上是 __________。(请填入具体内容)
    <class 'jpype._jclass.java.lang.Float'>

而不是我想要的普通Python浮点数。与普通的numpy浮点数组相比,

>>> b = array([[1.1, 2.1, 3.1], [4.1, 5.1, 6.1], [7.1, 8.1, 9.1]])
>>> type((b[0])[0])
<type 'numpy.float64'>

这里需要使用所需的浮点类型。

为了能够与Python程序的其他部分一起运行,我需要使用java Float.floatValue()将数组每个元素转换。

    arr = numpy.array(dataFloat)
    a = array([])
    for j in range(len(arr)):
        b = array([])
        if array_equal(a,[]):
           for i in arr.get(j):
              a = append(a, i.floatValue())
        else:
           for i in arr.get(j):
              b = append(b, i.floatValue())
           a = vstack((a, b))   

当有成千上万个元素需要处理时,这当然需要很长时间。

有没有人知道如何高效地完成这项工作?简单来说,我从JPype获取了许多java.lang.Float值,需要将它们转换为常规的Python浮点数值。


你能不能保留程序不变,在Java代码中启动一个Jython解释器呢? - Jakob Bowyer
首先,我不知道如何使用jython,也不确定它提供了什么。我认为JPype很好,因为我可以调用和使用我的Java类。这样,我就不必对我的Java代码进行任何特殊修改以便进行测试,只需要在Python代码中进行一些重写即可。到目前为止,我遇到的唯一问题是这个。让我们说我想继续使用JPype而不是去折腾其他的Java<->Python包 :) - Mattias
基本上,Jython 是在 JVM 上编写的 Python。您可以在 Java 中初始化 Jython 解释器,然后将 Python(基本上)输入其中。 - Jakob Bowyer
啊好的,那么我现在处理的类提供信息给Python程序的其他部分,而不是相反。那么在这种情况下,Jython就没有任何帮助了? - Mattias
2
Jython可以双向工作,但在这种情况下它无法帮助,因为Numpy部分是用C实现的,而Jython不能处理这些库。 - Daniel Teply
1个回答

0

我之前尝试过使用JPype,也遇到了一些类型转换的问题。也许你可以使用http://cython.org/来加速你的代码,这里有一些方法可以加快对numpy数据结构的访问速度:http://docs.cython.org/src/tutorial/numpy.html

另外一个评论:vstack和hstack可以处理任意的列表/元组。所以你可以像这样重写你的代码(未经测试)

arr = numpy.array(dataFloat)
a = []
for j in range(len(arr)):
    b = array([])
    for i in arr.get(j):
          b = append(b, i.floatValue())
    a.append(b)
a = vstack(a)   

如果避免调用append(),则可以进一步优化速度。更快的方法是使用固定大小N来分配数组b,例如使用zero(),然后填充值:

arr = numpy.array(dataFloat)
N = ....
a = []
for j in range(len(arr)):
    b = zeros((N,))
    for k in range(N):
          i =arr.get(j)[k]:
          b[k] = i.floatValue()
    a.append(b)
a = vstack(a)   

只有当你知道N的值时,它才能正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接