Проблема в том, что группы строк с одним и тем же Z могут иметь разные размеры, поэтому вы не можете объединить их в один массив 3D numpy, который позволил бы легко применить функцию к третьему измерению. Одно из решений - использовать for-l oop, другое - np.split
:
a = np.array([[0, 0, 1],
[1, 1, 2],
[4, 5, 1],
[4, 5, 2],
[4, 3, 1]])
a_sorted = a[a[:,2].argsort()]
inds = np.unique(a_sorted[:,2], return_index=True)[1]
a_split = np.split(a_sorted, inds)[1:]
# [array([[0, 0, 1],
# [4, 5, 1],
# [4, 3, 1]]),
# array([[1, 1, 2],
# [4, 5, 2]])]
f = np.sum # example of a function
result = list(map(f, a_split))
# [19, 15]
Но imho лучшее решение - использовать pandas и groupby, как это было предложено FBruzzesi. , Затем вы можете преобразовать результат в массив numpy.
EDIT : для полноты рассмотрим два других решения
Понимание списка:
b = np.unique(a[:,2])
result = [f(a[a[:,2] == z]) for z in b]
Pandas:
df = pd.DataFrame(a, columns=list('XYZ'))
result = df.groupby(['Z']).apply(lambda x: f(x.values)).tolist()
Это график производительности, который я получил за a = np.random.randint(0, 100, (n, 3))
:
Как видите, примерно до n = 10^5
«разделенное решение» является самым быстрым, но после этого решение pandas работает лучше.