如何将具有对象数据类型的Numpy 2D数组转换为常规的浮点数2D数组

33
作为我正在进行的更广泛计划的一部分,我最终得到了包含字符串、3D坐标等混合内容的对象数组。我知道与结构化数组相比,对象数组可能并不是很受欢迎,但我希望在不改变大量代码的情况下解决这个问题。
假设我的数组obj_array(有N行)的每一行都具有以下格式:
Single entry/object of obj_array:  ['NAME',[10.0,20.0,30.0],....] 

现在,我正在尝试加载这个对象数组并切分3D坐标块。直到这里,只需要简单地请求,一切都正常工作。

obj_array[:,[1,2,3]]

然而,结果也是一个对象数组,我将面临问题,因为我想用以下方法形成一个二维浮点数数组:

However the result is also an object array and I will face problem as I want to form a 2D array of floats with:
size [N,3] of N rows and 3 entries of X,Y,Z coordinates

目前,我正在循环遍历行,并将每一行分配给目标2D flot数组的一行,以解决问题。我想知道是否有更好的方式使用NumPy的数组转换工具?我尝试了一些方法,但无法解决问题。

Centers   = np.zeros([N,3])

for row in range(obj_array.shape[0]):
    Centers[row,:] = obj_array[row,1]

感谢


你能展示一个简单的示例代码吗?包括原始数据和转换代码。这将使得其他人更容易给出适当的建议。 - Floris
8个回答

28

棘手的小问题...我一直在摆弄这个玩具例子:

>>> arr = np.array([['one', [1, 2, 3]],['two', [4, 5, 6]]], dtype=np.object)
>>> arr
array([['one', [1, 2, 3]],
       ['two', [4, 5, 6]]], dtype=object)

我的第一个猜测是:

>>> np.array(arr[:, 1])
array([[1, 2, 3], [4, 5, 6]], dtype=object)

但是这会保留object数据类型,也许可以这样做:

>>> np.array(arr[:, 1], dtype=np.float)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: setting an array element with a sequence.

你通常可以通过以下方法解决这个问题:

>>> np.array(arr[:, 1], dtype=[('', np.float)]*3).view(np.float).reshape(-1, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected a readable buffer object

然而这里并不行,这让人感到有些困惑。显然,导致问题的原因是数组中的对象是列表,将列表替换为元组会解决这个问题:

>>> np.array([tuple(j) for j in arr[:, 1]],
...          dtype=[('', np.float)]*3).view(np.float).reshape(-1, 3)
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])

既然似乎没有完全令人满意的解决方案,最简单的可能是选择以下方式:

>>> np.array(list(arr[:, 1]), dtype=np.float)
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])

虽然这样可能不太高效,但更好的做法可能是采用类似以下的方法:

>>> np.fromiter((tuple(j) for j in arr[:, 1]), dtype=[('', np.float)]*3,
...             count=len(arr)).view(np.float).reshape(-1, 3)
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])

我是唯一一个不明白为什么 np.array(arr[:, 1], dtype=np.float) 不起作用的人? - Syzygy

13

根据Jaime的玩具示例,我认为你可以使用np.vstack()来简单地完成这个操作:

arr = np.array([['one', [1, 2, 3]],['two', [4, 5, 6]]], dtype=np.object)
float_arr = np.vstack(arr[:, 1]).astype(np.float)

无论您的对象数组中的“numeric”元素是1D numpy数组、列表还是元组,本方法都可适用。

6

这个方法非常适用于将对象转换为浮点数数组,之后的数字处理也非常容易。感谢上一篇帖子!我刚刚修改了它以包括任何DataFrame大小:

float_arr = np.vstack(arr[:, :]).astype(np.float)

这更像是一条评论而不是一个答案。它与ali_m的回答有关吗? - jogo

2

将对象数组转换为NumPy浮点数组速度更快: arr=np.array(arr, dtype=[('O', np.float)]).astype(np.float) - 从那里开始,没有循环,可以像在NumPy数组上一样索引它。但是您必须按块处理不同的数据类型arr[:, 1], arr[:,2]等等。我曾经遇到过一个与C++ DLL函数返回的NumPy元组对象具有相同问题 - 将17M个元素转换需要不到2秒。


如果有人尝试了上面的解决方案并对其进行了分析,它就不会被投下反对票。 - Matt
1
我用这种方法出现了“ValueError:使用序列设置数组元素”的错误。。例子:aa = [['5236',[1,2,0.3]],['63734',[6,1.5,0.0]]] bb = np.array(aa,dtype ='object') arr = np.array(bb [:,1],dtype =[('O',np.float)]). astype(np.float) - lightbox142

1
你可能需要使用结构化数组,这样当你需要独立访问名称和值时,就可以轻松地实现。在这个例子中,有两个数据点:
x = zeros(2, dtype=[('name','S10'), ('value','f4',(3,))])
x[0][0]='item1'
x[1][0]='item2'
y1=x['name']
y2=x['value']

结果为:
>>> y1
array(['item1', 'item2'], 
      dtype='|S10')
>>> y2
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.]], dtype=float32)

查看更多详细信息:http://docs.scipy.org/doc/numpy/user/basics.rec.html


1

1

np.array(list(arr), dtype=np.float) 会将数组中的所有元素一次性转换为浮点数。


1

当你有一个包含不同类型的数据集时,通常会出现这个问题,通常是在第一列或其他列中出现日期。

我通常的做法是将日期列存储在不同的变量中,并将其余的“X特征矩阵”放入X中。例如,我有日期和X。

然后我将转换应用于X矩阵:

X = np.array(list(X[:,:]), dtype=np.float)

希望能帮到你!


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