快速问题
我希望能够比较两个numpy结构化数组中特定的dtype字段,这些数组保证具有相同的dtype。我希望以一种允许每次调用函数时基于给定的输入比较不同字段的方式进行比较(即我无法轻松地为每个单独的字段硬编码比较)。
带有示例的详细问题
我试图比较具有相同dtype的两个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
中仅当 x
字段和 y
字段都比 b
中对应的字段要大的项。这很简单,我们可以再次执行以下操作:
newArr = a[np.array([np.array([a['pos']['x']>b['pos']['x']),a['pos']['y']>b['pos']['y'])).all(axis=0)]
这将返回一个空数组,这是正确的答案。
现在,假设我们有一个非常复杂的dtype(比如包含34个字段——参见这里的dtype示例),我们想要能够比较它们中的任何一个,但可能不是全部(类似于上一个示例,但总体上具有更多的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布尔数组中,然后我可以使用该数组从a中提取正确的条目。现在我想起来这可能是正确的方法。
我的长篇问题的结论。
尽管我认为我已经找到了解决这个问题的方法,但我仍然会发布这个问题,至少要看看是否有人有关于如何对结构化/掩码numpy数组进行逻辑比较的想法,因为我认为这将是一个有用的知识点,以及是否有比我想到的更好的方法。请注意,您可以通过逐行复制“具有示例的长问题”部分中的片段来轻松地形成MWE,我没有看到任何理由通过执行此操作来占用更多空间。
dtype=[('firstGroup',[('homework',int),('classwork',int)]),('roomsOfTheHouse',[('bathroom',[('sink',str),('tub',str)]),('kitchen',[('floor',str),('counter',str)])]
,我不确定它是否能够被处理。 - Andrew