Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
快速python算法(numpy或pandas?),用于查找与另一个数组中的元素匹配的数组元素索引_Python_Performance_Algorithm_Numpy_Pandas - Fatal编程技术网

快速python算法(numpy或pandas?),用于查找与另一个数组中的元素匹配的数组元素索引

快速python算法(numpy或pandas?),用于查找与另一个数组中的元素匹配的数组元素索引,python,performance,algorithm,numpy,pandas,Python,Performance,Algorithm,Numpy,Pandas,我正在寻找一种快速方法来确定两个数组的交叉匹配索引,定义如下 我有两个非常大(>1e7个元素)的结构化数组,一个称为成员,另一个称为组。两个数组都有一个groupID列。groups数组的groupID项是唯一的,members数组的groupID项不是唯一的 “组”数组有一个名为“质量”的列。members数组有一个名为groupmass的列(当前为空)。我希望将正确的groupmass分配给groupID与其中一个组匹配的成员元素。这将通过以下方式实现: members['groupmass

我正在寻找一种快速方法来确定两个数组的交叉匹配索引,定义如下

我有两个非常大(>1e7个元素)的结构化数组,一个称为成员,另一个称为组。两个数组都有一个groupID列。groups数组的groupID项是唯一的,members数组的groupID项不是唯一的

“组”数组有一个名为“质量”的列。members数组有一个名为groupmass的列(当前为空)。我希望将正确的groupmass分配给groupID与其中一个组匹配的成员元素。这将通过以下方式实现:

members['groupmass'][idx_matched_members] = groups['mass'][idx_matched_groups]

所以我需要一个快速的例程来计算两个索引数组idx_匹配的成员和idx_匹配的组。这类任务似乎非常常见,以至于像numpy或pandas这样的包很可能会有一个优化的解决方案。有人知道专业开发、自制或其他解决方案吗?

这可以通过
pandas
使用
map
来完成,以使用一列的数据映射另一列的数据。下面是一个示例数据:

members = pandas.DataFrame({
    'id': np.arange(10),
    'groupID': np.arange(10) % 3,
    'groupmass': np.zeros(10)
})

groups = pandas.DataFrame({
    'groupID': np.arange(3),
    'mass': np.random.randint(1, 10, 3)
})
这将为您提供以下数据:

>>> members
   groupID  groupmass  id
0        0          0   0
1        1          0   1
2        2          0   2
3        0          0   3
4        1          0   4
5        2          0   5
6        0          0   6
7        1          0   7
8        2          0   8
9        0          0   9
>>> groups
   groupID  mass
0        0     3
1        1     7
2        2     4
然后:


如果您经常想使用groupID作为
组的索引,您可以永久地将其设置为这样,这样您就不必每次都使用
设置索引。

这可以通过
熊猫
使用
映射
使用另一列的数据从一列映射数据来完成。下面是一个示例数据:

members = pandas.DataFrame({
    'id': np.arange(10),
    'groupID': np.arange(10) % 3,
    'groupmass': np.zeros(10)
})

groups = pandas.DataFrame({
    'groupID': np.arange(3),
    'mass': np.random.randint(1, 10, 3)
})
这将为您提供以下数据:

>>> members
   groupID  groupmass  id
0        0          0   0
1        1          0   1
2        2          0   2
3        0          0   3
4        1          0   4
5        2          0   5
6        0          0   6
7        1          0   7
8        2          0   8
9        0          0   9
>>> groups
   groupID  mass
0        0     3
1        1     7
2        2     4
然后:


如果您经常想使用groupID作为
组的索引,您可以永久地将其设置为这样,这样您就不必每次都使用
设置索引。

这可以通过
熊猫
使用
映射
使用另一列的数据从一列映射数据来完成。下面是一个示例数据:

members = pandas.DataFrame({
    'id': np.arange(10),
    'groupID': np.arange(10) % 3,
    'groupmass': np.zeros(10)
})

groups = pandas.DataFrame({
    'groupID': np.arange(3),
    'mass': np.random.randint(1, 10, 3)
})
这将为您提供以下数据:

>>> members
   groupID  groupmass  id
0        0          0   0
1        1          0   1
2        2          0   2
3        0          0   3
4        1          0   4
5        2          0   5
6        0          0   6
7        1          0   7
8        2          0   8
9        0          0   9
>>> groups
   groupID  mass
0        0     3
1        1     7
2        2     4
然后:


如果您经常想使用groupID作为
组的索引,您可以永久地将其设置为这样,这样您就不必每次都使用
设置索引。

这可以通过
熊猫
使用
映射
使用另一列的数据从一列映射数据来完成。下面是一个示例数据:

members = pandas.DataFrame({
    'id': np.arange(10),
    'groupID': np.arange(10) % 3,
    'groupmass': np.zeros(10)
})

groups = pandas.DataFrame({
    'groupID': np.arange(3),
    'mass': np.random.randint(1, 10, 3)
})
这将为您提供以下数据:

>>> members
   groupID  groupmass  id
0        0          0   0
1        1          0   1
2        2          0   2
3        0          0   3
4        1          0   4
5        2          0   5
6        0          0   6
7        1          0   7
8        2          0   8
9        0          0   9
>>> groups
   groupID  mass
0        0     3
1        1     7
2        2     4
然后:


如果您经常想使用groupID作为
组的索引,您可以将其永久设置,这样您就不必每次都使用
set\u index

下面是一个仅使用
numpy
设置
质量的示例。它确实使用迭代,所以对于大型阵列,它不会很快

对于仅10行,这比同等的
pandas
要快得多。但随着数据集变得越来越大(例如M=10000),
pandas
要好得多。
pandas
的设置时间较大,但每行迭代时间较低

生成测试阵列:

dt_members = np.dtype({'names':['groupID','groupmass'], 'formats': [int, float]})
dt_groups =  np.dtype({'names':['groupID', 'mass'], 'formats': [int, float]})

N, M = 5, 10
members = np.zeros((M,), dtype=dt_members)    
groups = np.zeros((N,), dtype=dt_groups)
members['groupID'] = np.random.randint(101, 101+N, M)
groups['groupID'] = np.arange(101, 101+N)
groups['mass']  = np.arange(1,N+1)

def getgroup(id):
    idx = id==groups['groupID']
    return groups[idx]

members['groupmass'][:] = [getgroup(id)['mass'] for id in members['groupID']]
python2
中,迭代可以使用
map

members['groupmass'] =  map(lambda x: getgroup(x)['mass'], members['groupID'])

通过最小化重复订阅,我可以将速度提高约2倍,例如

def setmass(members, groups):
    gmass = groups['mass']
    gid = groups['groupID']
    mass = [gmass[id==gid] for id in members['groupID']]
    members['groupmass'][:] = mass

但是如果
groups['groupID']
可以映射到
arange(N)
,那么我们可以在速度上有一个很大的飞跃。通过将相同的映射应用于
成员['groupID']
,它变成了一个简单的数组索引问题

在我的示例数组中,
groups['groupID']
只是
arange(N)+101
。所以映射只是减去最小值

def setmass1(members, groups):
    members['groupmass'][:] = groups['mass'][members['groupID']-groups['groupID'].min()]
这比我以前的代码快300倍,比
pandas
解决方案(对于10000500阵列)好8倍

我怀疑熊猫是这样做的
pgroups.set_index('groupID')。mass
mass
系列,添加了
.index
属性。(我可以用更通用的数组来测试)

在更一般的情况下,它可能有助于对
组进行排序
,并在必要时填补一些索引空白


这是一个“矢量化”的解决方案——没有迭代。但它必须计算一个非常大的矩阵(组的长度乘以成员的长度),因此速度不快(
np,其中
是最慢的一步)


下面是一个仅使用
numpy
设置
mass
的示例。它确实使用迭代,所以对于大型阵列,它不会很快

对于仅10行,这比同等的
pandas
要快得多。但随着数据集变得越来越大(例如M=10000),
pandas
要好得多。
pandas
的设置时间较大,但每行迭代时间较低

生成测试阵列:

dt_members = np.dtype({'names':['groupID','groupmass'], 'formats': [int, float]})
dt_groups =  np.dtype({'names':['groupID', 'mass'], 'formats': [int, float]})

N, M = 5, 10
members = np.zeros((M,), dtype=dt_members)    
groups = np.zeros((N,), dtype=dt_groups)
members['groupID'] = np.random.randint(101, 101+N, M)
groups['groupID'] = np.arange(101, 101+N)
groups['mass']  = np.arange(1,N+1)

def getgroup(id):
    idx = id==groups['groupID']
    return groups[idx]

members['groupmass'][:] = [getgroup(id)['mass'] for id in members['groupID']]
python2
中,迭代可以使用
map

members['groupmass'] =  map(lambda x: getgroup(x)['mass'], members['groupID'])

通过最小化重复订阅,我可以将速度提高约2倍,例如

def setmass(members, groups):
    gmass = groups['mass']
    gid = groups['groupID']
    mass = [gmass[id==gid] for id in members['groupID']]
    members['groupmass'][:] = mass

但是如果
groups['groupID']
可以映射到
arange(N)
,那么我们可以在速度上有一个很大的飞跃。通过将相同的映射应用于
成员['groupID']
,它变成了一个简单的数组索引问题

在我的示例数组中,
groups['groupID']
只是
arange(N)+101
。所以映射只是减去最小值

def setmass1(members, groups):
    members['groupmass'][:] = groups['mass'][members['groupID']-groups['groupID'].min()]
这比我以前的代码快300倍,比
pandas
解决方案(对于10000500阵列)好8倍

我怀疑熊猫是这样做的
pgroups.set_index('groupID')。mass
mass
系列,添加了
.index
属性。(我可以用更通用的数组来测试)

在更一般的情况下,它可能有助于对
组进行排序
,并在必要时填补一些索引空白


这是一个“矢量化”的解决方案——没有迭代。但它必须计算一个非常大的矩阵(组的长度乘以长度o)