Вот как вы можете рассчитать это с помощью NumPy:
import numpy as np
def mean_by_class(t, classes=None):
# Classes should be passed if you want to ensure
# that all classes are in the output even if they
# are not in the current t vector
if classes is None:
classes = np.unique(t[:, 0])
bins = np.r_[classes, classes[-1] + 1]
h, _ = np.histogram(t[:, 0], bins)
d = np.digitize(t[:, 0], bins, right=True)
out = np.zeros(len(classes), t.dtype)
np.add.at(out, d, t[:, 1])
out /= h.clip(min=1)
return np.c_[classes, out]
t1 = np.array([[10, 0.1 ], [30, 0.05], [30, 0.1 ],
[20, 0.1 ], [10, 0.05], [10, 0.05],
[ 0, 0.5 ], [20, 0.05], [10, 0.0 ]],
dtype=np.float64)
print(mean_by_class(t1))
# [[ 0. 0.5 ]
# [10. 0.05 ]
# [20. 0.075]
# [30. 0.075]]
В качестве примечания, возможно, не лучший выбор для хранения значений классов, которые являются целыми числами, в массиве с плавающей запятой. Вместо этого вы можете использовать структурированный массив , например, так:
import numpy as np
def mean_by_class(t, classes=None):
if classes is None:
classes = np.unique(t['class'])
bins = np.r_[classes, classes[-1] + 1]
h, _ = np.histogram(t['class'], bins)
d = np.digitize(t['class'], bins, right=True)
out = np.zeros(len(classes), t.dtype)
out['class'] = classes
np.add.at(out['p'], d, t['p'])
out['p'] /= h.clip(min=1)
return out
t1 = np.array([(10, 0.1 ), (30, 0.05), (30, 0.1 ),
(20, 0.1 ), (10, 0.05), (10, 0.05),
( 0, 0.5 ), (20, 0.05), (10, 0.0 )],
dtype=[('class', np.int32), ('p', np.float64)])
print(mean_by_class(t1))
# [( 0, 0.5 ) (10, 0.05 ) (20, 0.075) (30, 0.075)]