Вы можете сделать это очень эффективно, используя базовый массив numpy
:
def square_mean(arr, y, x):
yy, xx = arr.shape
vals = arr.reshape(y, yy//y, x, xx//x).mean((1,3))
return vals
pd.DataFrame(square_mean(df.values, 2, 2))
0 1
0 3.5 11.5
1 5.5 13.5
Это решение работает из-за некоторого умного изменения формы массиваВот как работает изменение формы:
yy, xx = arr.shape
vals = arr.reshape(2, yy//2, 2, xx//2)
print(vals)
[[[[ 1. 5.]
[ 9. 13.]]
[[ 2. 6.]
[10. 14.]]]
[[[ 3. 7.]
[11. 15.]]
[[ 4. 8.]
[12. 16.]]]]
Как видите, массив был преобразован в куски, которые мы затем можем использовать для вычисления среднего.
Это решение масштабируется до всех входных размеров, просто выберите x
в качестве количества чанков вдоль оси x и y
в качестве количества чанков вдоль оси y:
df = pd.DataFrame(np.random.randint(1, 5, (10, 10)))
0 1 2 3 4 5 6 7 8 9
0 1 3 4 2 3 3 3 2 1 2
1 3 3 4 1 3 4 4 4 1 3
2 2 3 2 2 4 4 1 1 1 1
3 1 2 1 2 1 3 1 1 2 3
4 2 2 3 4 3 2 4 3 4 2
5 3 3 1 4 2 1 2 3 1 3
6 2 1 3 4 3 2 3 4 3 4
7 2 3 4 2 1 1 1 1 3 2
8 4 3 2 2 2 2 2 1 3 3
9 3 2 1 2 1 3 4 2 4 4
Мы можем разделить на любое количество кусков:
square_mean(df.values, 2, 2)
array([[2.44, 2.4 ],
[2.4 , 2.48]])
square_mean(df.values, 5, 5)
array([[2.5 , 2.75, 3.25, 3.25, 1.75],
[2. , 1.75, 3. , 1. , 1.75],
[2.5 , 3. , 2. , 3. , 2.5 ],
[2. , 3.25, 1.75, 2.25, 3. ],
[3. , 1.75, 2. , 2.25, 3.5 ]])