二维Numpy数组在组上最快的应用功能

假设我有一个2D数据矩阵,我想对该矩阵中的组应用一个函数。

例如:

二维Numpy数组在组上最快的应用功能

。 。 。 。

二维Numpy数组在组上最快的应用功能

对于每个唯一索引,我都想应用一些功能intent.setType("application/zip,application/octet-stream,application/x-zip-compressed,multipart/x-zip")

例如对于具有f的组,将函数index = 1应用于值f(请参见第一列),对于组0.556,0.492,0.148,将函数应用于值index = 2

另外:

  1. 该功能必须将结果广播到输入数据的原始大小。
  2. 每列的组是唯一的。您可以在上面的示例中看到这一点,其中每个组仅包含同一列中的值。

那么用Python执行此操作的绝对最快的方法是什么?

我目前正在执行以下操作(使用随机数据[2000x500]和每列5个随机组):

0.043

对于我的硬件,此计算大约需要10秒钟才能完成。有没有更快的方法可以做到这一点?

lulu2008137 回答:二维Numpy数组在组上最快的应用功能

不确定是否最快,但是此矢量化解决方案要快得多:

import numpy as np
import time

np.random.seed(0)
rows = 2000
cols = 500
ngroup = 5

data = np.random.rand(rows,cols)
groups = np.random.randint(ngroup,size=(rows,cols)) + 10*np.tile(np.arange(cols),(rows,1))

t = time.perf_counter()
# Flatten the data
dataf = data.ravel()
groupsf = groups.ravel()
# Sort by group
idx_sort = groupsf.argsort()
datafs = dataf[idx_sort]
groupsfs = groupsf[idx_sort]
# Find group bounds
idx = np.nonzero(groupsfs[1:] > groupsfs[:-1])[0]
idx = np.concatenate([[0],idx + 1,[len(datafs)]])
# Sum by groups
a = np.add.reduceat(datafs,idx[:-1])
# Count group elements
c = np.diff(idx)
# Compute group means
m = a / c
# Repeat means and counts to match data shape
means = np.repeat(m,c)
counts = np.repeat(c,c)
# Compute variance and std
v = np.add.reduceat(np.square(datafs - means),idx[:-1]) / c
s = np.sqrt(v)
# Repeat stds
stds = np.repeat(s,c)
# Compute result values
resultfs = (datafs - means) / stds
# Undo sorting
idx_unsort = np.empty_like(idx_sort)
idx_unsort[idx_sort] = np.arange(len(idx_sort))
resultf = resultfs[idx_unsort]
# Reshape back
result = np.reshape(resultf,data.shape)
print(time.perf_counter() - t)
# 0.09932469999999999

# Previous method to check result
t = time.perf_counter()
result_orig= np.zeros(data.shape)
f = lambda x: (x-np.average(x))/np.std(x)
for group in np.unique(groups):
    location = np.where(groups == group)
    group_data = data[location[0],location[1]]
    result_orig[location[0],location[1]] = f(group_data)
print(time.perf_counter() - t)
# 6.0592527

print(np.allclose(result,result_orig))
# True

编辑:要计算中位数,您可以执行以下操作:

# Flatten the data
dataf = data.ravel()
groupsf = groups.ravel()
# Sort by group and value
idx_sort = np.lexsort((dataf,groupsf))
datafs = dataf[idx_sort]
groupsfs = groupsf[idx_sort]
# Find group bounds
idx = np.nonzero(groupsfs[1:] > groupsfs[:-1])[0]
idx = np.concatenate([[0],[len(datafs)]])
# Count group elements
c = np.diff(idx)
# Meadian index
idx_median1 = c // 2
idx_median2 = idx_median1 + (c % 2) - 1
idx_median1 += idx[:-1]
idx_median2 += idx[:-1]
# Get medians
meds = 0.5 * (datafs[idx_median1] + datafs[idx_median2])

这里的窍门是使用np.lexsort而不是np.argsort来按组和值进行排序。 meds将是一个数组,其中包含每个组的中位数,然后,您可以在其上使用np.repeat,包括均值或其他任何想要的东西。

本文链接:https://www.f2er.com/3150140.html

大家都在问