gpt4 book ai didi

python - 比较 numpy 结构化数组

转载 作者:太空狗 更新时间:2023-10-30 02:43:09 34 4
gpt4 key购买 nike

快速问题

我希望能够比较来自保证具有相同数据类型的两个 numpy 结构化数组的特定数据类型字段。我想以一种允许我们比较的字段每次根据给定输入调用函数时不同的方式来执行此操作(即我不能轻易地对每个单独字段的比较进行硬编码)

例子很长

我正在尝试比较两个具有相同数据类型的 numpy 结构化数组的特定字段。例如,假设我们有

import numpy as np
from io import BytesIO

a = np.genfromtxt(BytesIO('12 23 0|23.2|17.9|0\n12 23 1|13.4|16.9|0'.encode()),dtype=[('id','U7'),('pos',[('x',float),('y',float)]),('flag','U1')],delimiter='|')

b = np.genfromtxt(BytesIO(' |23.0|17.91|0'.encode()),dtype=[('id','U7'),('pos',[('x',float),('y',float)]),('flag','U1')],delimiter='|')

给出

In[156]: a
Out[154]:
array([('12 23 0', (23.2, 17.9), '0'), ('12 23 1', (13.4, 16.9), '0')],
dtype=[('id', '<U7'), ('pos', [('x', '<f8'), ('y', '<f8')]), ('flag', '<U1')])

In[153]: b
Out[151]:
array([('', (23.0, 17.91), '0')],
dtype=[('id', '<U7'), ('pos', [('x', '<f8'), ('y', '<f8')]), ('flag', '<U1')])

现在假设我想检查并找到 a 中的任何条目,其 a['pos']['x'] 字段大于 b['pos']['x'] 字段并将这些条目返回到一个新的 numpy 数组,像这样的东西会起作用

newArr = a[a["pos"]["x"]>b["pos"]["x"]]

现在假设我们只想保留 a 中的条目,其中 xy 字段都大于它们在 中的对应项b。这非常简单,因为我们可以再次这样做

newArr = a[np.array([np.array([a['pos']['x']>b['pos']['x']),a['pos']['y']>b['pos']['y'])).all(axis=0)]

它返回一个空数组,这是正确答案。

但是现在,假设我们有一个非常复杂的数据类型用于这些数组(比如有 34 个字段——请参阅 here 以获取我正在使用的数据类型的示例)并且我们希望能够比较任何它们,但可能不是全部(类似于前面的示例,但总体上有更多的 dtype 字段,我们想要比较的字段也更多。此外,如果我们想要比较的字段可以在运行期间发生变化(所以我们不能真的很难按照我上面的方式编码)。这就是我试图找到解决方案的问题。

我目前(未完成)的解决方案尝试

使用屏蔽数组

解决这个问题的第一个想法是使用掩码数组来选择我们要比较的数据类型字段。像这样(假设我们可以使所有比较都相同):

mask = np.ones(z.shape,dtype=[('id',bool),('pos',[('x',bool),('y',bool)]),('flag',bool)])
# unmask the x and y fields so we can compare them
mask['pos']['x']=0
mask['pos']['y']=0

maskedA = np.ma.masked_array(a, mask=mask)
# We need to do this or the masked array gets angry (at least in python 3)
b.shape = (1,)

maskedB = np.ma.masked_array(b, mask=mask)

现在我想做类似的事情

test = (maskedA>maskedB).any(axis=1)

但这不起作用,因为您可以像这样比较结构化数组 --

TypeError: unorderable types: MaskedArray() > MaskedArray()

我也试过压缩屏蔽数组

test = (maskedA.compressed()>maskedB.compressed()).any(axis=1)

这会导致不同的错误

TypeError: ufunc 'logical_not' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

现在,我意识到上述错误很可能是因为我不完全理解结构化数组和掩码数组的工作原理,但这也是我问这个问题的部分原因。有什么方法可以使用掩码数组来做这样的事情吗?

我刚才想到的解决方案可能会奏效,而且整体上可能更好......

所以我在写这篇文章时想到的另一个选择是在我解析用户输入以形成数组 b 时进行比较。它实际上只是向解析器中的每个条件添加几行以进行比较并将结果添加到一个 numpy bool 数组中,然后我可以使用它从 a 中提取正确的条目。现在我想这可能是要走的路。

我漫长而杂乱无章的问题的结论。

尽管我认为我找到了解决这个问题的方法,但我仍然会至少发布这个问题一点点,看看是否 (a) 是否有人对如何与结构化/屏蔽进行逻辑比较有任何想法numpy 数组,因为我认为了解它是一件有用的事情,并且 (b) 看看是否有人比我想出的想法更好。请注意,您可以通过逐行复制“示例的长期问题”部分中的片段来非常轻松地形成 MWE,我认为这样做没有任何理由占用更多空间。

最佳答案

要对列序列进行比较,您必须使用 Python 循环。循环可以以列表理解的形式出现,例如:

In [87]: np.all([a['pos'][key] > b['pos'][key] for key in a['pos'].dtype.names], axis=0)
Out[87]: array([False, False], dtype=bool)

这将为 a['pos'] 中的每个字段计算 a['pos'][key] > b['pos'][key],并且然后沿 0 轴使用 np.all 减少数组。

如果您希望将比较应用于某些字段列表,您当然可以将 a['pos'].dtype.names 替换为该列表。

关于python - 比较 numpy 结构化数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34421249/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com