2

R 用户在这里,我正在尝试我的第一个 Python 项目以利用 Numba。我读过 Numba 与 Numpy 配合得很好,但与 Pandas 配合得不好,所以我试图避免使用 Pandas。我当前的问题实际上与 Numba 无关,但我想提一下它作为我避免使用 Pandas 的原因。

我有两个 Numpy 结构化数组,一个有很多重复。我正在尝试使用“numpy.lib.recfunctions.join_by”函数加入它们,但文档明确指出重复会导致问题。任何人都可以为我的所有重复项推荐任何解决方法吗?

这是一个类似于我的情况的示例:

import numpy as np
import numpy.lib.recfunctions as rfn

a = np.zeros(4, dtype={'names':('name', 'age'),
                       'formats':('U10','f8')})
a['name'] = ['Alex', 'Billy', 'Charlie', 'Dave']
a['age'] = [25, 25, 75, 75]

b = np.zeros(2, dtype={'names':('age', 'senior'),
                       'formats':('f8', 'i4')})
b['age'] = [25, 75]
b['senior'] = [0, 1]

c = rfn.join_by('age', a, b, jointype='leftouter', usemask=False)

print(c)
[(25., 'Alex',      0) (75., 'Billy',      1) (75., 'Charlie', 999999)
(75., 'Dave', 999999)]

这 (1) 将比利的“年龄”从 25 岁更改为 75 岁,并且 (2) 为查理和戴夫提供了 999999 的“高级”值。

有人对此功能的重复限制有解决方法吗?提前致谢。

4

2 回答 2

0

为什么不加入而不做比较?这在您的示例中效果更好。

我意识到这不适用于您有一组必须映射到值的键的任意连接。在那里,我建议您遍历键并从头开始构建数组,从一个填充了 NaN 的空数组开始,并使用np.where它来查找和替换数组中的值。

使用此起始代码:

import numpy as np
import numpy.lib.recfunctions as rfn

a = np.zeros(4, dtype={'names':('name', 'age'),
                       'formats':('U10','f8')})
a['name'] = ['Alex', 'Billy', 'Charlie', 'Dave']
a['age'] = [25, 25, 75, 75]

你可以做:

d = rfn.append_fields(a, names='senior', data=(a['age'] >= 65).astype(int))
print(d)

这导致:

[('Alex', 25.0, 0) ('Billy', 25.0, 0) ('Charlie', 75.0, 1) ('Dave', 75.0, 1)]

使用 Numba 的主要原因是加速 python 代码。Numpy 和 Pandas 已经在底层实现了这些加速。

于 2019-03-21T04:34:55.550 回答
0

在封面下,recfunctions 通常构造一个新的 dtype 和“空白”结果数组。然后他们按字段名称复制值。我没有研究过join_by,但我可以想象你的加入是这样的:

In [11]: a.dtype                                                                          
Out[11]: dtype([('name', '<U10'), ('age', '<f8')])
In [12]: b.dtype                                                                          
Out[12]: dtype([('age', '<f8'), ('senior', '<i4')])
In [13]: b.dtype[1]                                                                       
Out[13]: dtype('int32')
In [14]: b.dtype.descr                                                                    
Out[14]: [('age', '<f8'), ('senior', '<i4')]

In [16]: dt = np.dtype(a.dtype.descr+[b.dtype.descr[1]])                                  
In [17]: dt                                                                               
Out[17]: dtype([('name', '<U10'), ('age', '<f8'), ('senior', '<i4')])

In [18]: e = np.zeros(a.shape, dt)                                                        
In [19]: for name in a.dtype.names: 
    ...:     e[name] = a[name] 
    ...:                                                                                  

In [21]: e                                                                                
Out[21]: 
array([('Alex', 25., 0), ('Billy', 25., 0), ('Charlie', 75., 0),
       ('Dave', 75., 0)],
      dtype=[('name', '<U10'), ('age', '<f8'), ('senior', '<i4')])

经过反复试验,我发现了这种将b年龄与a(现在e)配对的方法:

In [23]: e['age'][:,None]==b['age']                                                       
Out[23]: 
array([[ True, False],
       [ True, False],
       [False,  True],
       [False,  True]])
In [25]: np.where(Out[23])                                                                
Out[25]: (array([0, 1, 2, 3]), array([0, 0, 1, 1]))

现在只需将相应的“高级”值复制be

In [27]: e['senior'][Out[25][0]] = b['senior'][Out[25][1]]                                
In [28]: e                                                                                
Out[28]: 
array([('Alex', 25., 0), ('Billy', 25., 0), ('Charlie', 75., 1),
       ('Dave', 75., 1)],
      dtype=[('name', '<U10'), ('age', '<f8'), ('senior', '<i4')])

底层逻辑不依赖于这些结构化数组。我们也有单独的names, ages,senior_category_age等的一维数组。

recfunctions没有太多用处 - 从单独的包装和有限的 SO 问题可以看出。然而,我认为最近多字段索引的变化将增加它的使用,至少对于新添加的功能。

https://docs.scipy.org/doc/numpy/user/basics.rec.html#accessing-multiple-fields

于 2019-03-21T05:59:37.233 回答