我想以这种方式拆分2D数组:
示例:
从这个4x4 2D阵列:
np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
创建这五个2x2 2D阵列,具有单位位移(移位):
np.array([[1,2],[3,4]])
np.array([[4,5],[6,7]])
np.array([[7,8],[9,10]])
np.array([[10,11],[12,13]])
np.array([[13,14],[15,16]])
在一般情况下,从NXN 2D阵列(方阵)开始,尽可能多地创建具有MXM形状的Y 2D阵列。
更确切地说:要创建输出数组,不一定要使用行中的所有值。
示例:
从2D 8x8数组中,值为1到64,如果我想在2D 2x2数组中拆分此数组,则8x8数组中的第一行是1到8的行,第一个输出2D 2x2数组将是是np.array([[1,2],[3,4]]),第二个输出2D 2x2数组将是np.array([[4,5],[6,7]])...它一直持续到最后一个输出2D数组,即np.array([[61,62],[63,64]])。看看每个2D 2x2阵列都没有填充行中的所有值(CORRECT)。并且存在从前一个数组到下一个数组的单一位移(移位)。
有一种Numpy方法可以做到这一点吗?
MSeifert在这里回答(How to split an 2D array, creating arrays from "row to row" values)一个问题解决了这个问题的近95%,除了单一位移(移位)部分。
所以,从4x4 2D数组示例:
np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
而不是创建这四个2x2 2D阵列(没有单位移位/位移):
np.array([[1,2],[3,4]])
np.array([[5,6],[7,8]])
np.array([[9,10],[11,12]])
np.array([[13,14],[15,16]])
创建这些五个2x2 2D阵列(具有单位移位/位移):
np.array([[1,2],[3,4]])
np.array([[4,5],[6,7]])
np.array([[7,8],[9,10]])
np.array([[10,11],[12,13]])
np.array([[13,14],[15,16]])
当然,它应该适用于给定方形NXN 2D阵列的一般情况,以创建Y MXM方形2D阵列。
示例:从60x60平方的2d阵列中,创建Y MXM方形2D阵列(例如10x10)。
另外:我需要知道与原始方形2D阵列(在示例中为4x4 2D阵列)的点数相关的规则是什么,以及迷你方形2D阵列的点(示例中为2X2 2D阵列) )。在这种情况下,给定16个点(4x4 2D阵列),可以创建5个2x2 2D阵列(每个阵列有4个点)。
答案 0 :(得分:3)
子阵列完全适合的条件是(M+1)*(M-1)
除(N+1)*(N-1)
,您可以放置的子阵列数是这些数字的商。请注意,这些数字等于M*M-1
和N*N-1
。在这种形式下,该规则也适用于非方形矩阵。
实施例
M N M*M-1 N*N-1 Y
-----------------------------
3 5 8 24 3
3 7 8 48 6
5 7 24 48 2
4 11 15 120 8
实施:请注意,这会将重叠的视图返回到原始数组中。如果要修改它们,可能需要复制。另请注意,此实现适合尽可能多的子方形,较大矩阵中的任何剩余元素都会被删除。
更新:我添加了两个函数,用于计算给定N
所有可能的M
,反之亦然。
输出:
# Testing predictions ...
# ok
# M = 105
# solutions: [105, 1273, 1377, 4135, 4239, 5407, 5511, 5513]
# this pattern repeats at offsets 5512, 11024, 16536, ...
# N = 1000001
# solutions: [2, 3, 4, 5, 7, 9, 11, 31, 49, 1000001]
# example N, M = (5, 3)
# [[[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]]
# [[ 8 9 10]
# [11 12 13]
# [14 15 16]]
# [[16 17 18]
# [19 20 21]
# [22 23 24]]]
代码:
import numpy as np
import sympy
import itertools as it
import functools as ft
import operator as op
def get_subsquares(SqNN, M0, M1=None):
M1 = M0 if M1 is None else M1
N0, N1 = SqNN.shape
K = (N0*N1-1) // (M0*M1-1)
SqNN = SqNN.ravel()
s, = SqNN.strides
return np.lib.stride_tricks.as_strided(SqNN, (K, M0, M1),
(s*(M0*M1-1), s*M1, s))
def get_M_for_N(N):
"""Given N return all possible M
"""
assert N >= 2
f = 1 + (N & 1)
factors = sympy.factorint((N+1)//f)
factors.update(sympy.factorint((N-1)//f))
if f == 2:
factors[2] += 2
factors = [ft.reduce(op.mul, fs) for fs in it.product(
*([a**k for k in range(n+1)] for a, n in factors.items()))]
return [fs + 1 for fs in sorted(set(factors) & set(fs - 2 for fs in factors)) if (N*N-1) % (fs * (fs+2)) == 0]
def get_N_for_M(M):
"""Given M return all possible N in the form period, smallest
smallest is a list of all solutions between M and M*M if M is even
and between M and (M*M+1) / 2 if M is odd, all other solutions can be
obtained by adding multiples of period
"""
assert M >= 2
f = 1 + (M & 1)
factors = sympy.factorint((M+1)//f)
factors.update(sympy.factorint((M-1)//f))
factors = [k**v for k, v in factors.items()]
rep = (M+1)*(M-1) // f
f0 = [ft.reduce(op.mul, fs) for fs in it.product(*zip(it.repeat(1), factors))]
f1 = [rep // (f*a) for a in f0]
inv = [f if b==1 else f*b + 2 if a==1 else 2 * sympy.mod_inverse(a, b)
for a, b in zip(f1, f0)]
if f==1:
inv[1:-1] = [a%b for a, b in zip(inv[1:-1], f0[1:-1])]
return rep, sorted(a*b - 1 for a, b in zip(f1, inv))
def test_predict(N):
def brute_force(a, b):
return [i for i in range(a, b) if (i*i-1) % (a*a-1) == 0]
for x in range(2, N+1):
period, pred = get_N_for_M(x)
assert brute_force(x, period*4+2) \
== [a + b for b in range(0, 4*period, period) for a in pred]
def brute_force(b):
return [i for i in range(2, b+1) if (b*b-1) % (i*i-1) == 0]
for x in range(2, N+1):
assert brute_force(x) == get_M_for_N(x)
print('ok')
# test
print("Testing predictions ...")
test_predict(200)
print()
# examples
M = 105
period, pred = get_N_for_M(M)
print(f"M = {M}")
print(f"solutions: {pred}")
print(f"this pattern repeats at offsets {period}, {2*period}, {3*period}, ...")
print()
N = 1000001
pred = get_M_for_N(N)
print(f"N = {N}")
print(f"solutions: {pred}")
print()
N, M = 5, 3
SqNN = np.arange(N*N).reshape(N, N)
print(f"example N, M = ({N}, {M})")
print(get_subsquares(SqNN, M))