我正在使用以下代码来重塑形状为 (625,) 的对象:
u1 = np.linspace(16, 20, 25)
u2 = np.linspace(16, 20, 25)
u1, u2 = np.meshgrid(u1, u2)
U = np.vstack((u1.flatten(), u2.flatten()))
Z = Z.reshape(u1.shape)
结果是(25,25)的形状
现在,我的问题是:如何重塑具有形状
(500,)
的对象?
(25,25)
u1 = np.linspace(16, 20, math.sqrt(500))
不起作用,因为
np.linspace
需要整数作为样本数量
你能帮忙吗?
这是一种尽可能接近方阵的方法。这相当于找到
n
的两个整数因子:p, q
的问题,使得p * q == n
和p
尽可能接近sqrt(n)
。这个问题已经被提出,例如在 Math StackExchange here 中,已经确定没有“快速方法”可以做到这一点(例如,参见 this Fantasy comment 或 answer 关于这是 RSA 优势的论点)。关于SO,也有一个类似的问题here。
下面,我们编写了一个算法,该算法对
n
使用简单的因式分解,并搜索所有可能的因子组合(幂集),但不重复。
def factors(n):
while n > 1:
for i in range(2, n + 1):
if n % i == 0:
n //= i
yield i
break
然后,修改后的
powerset
仅发出独特的组合:
from itertools import chain, combinations
def uniq_powerset(iterable):
"""
Similar to powerset(it) but without repeats.
uniq_powerset([1,1,2]) --> (), (1,), (2,), (1, 1), (1, 2), (1, 1, 2)"""
s = list(iterable)
return chain.from_iterable(set(combinations(s, r)) for r in range(len(s)+1))
最后,我们的函数找到
n
的“方根”:
from math import isqrt
from math import isqrt
def squarishrt(n):
pmax = isqrt(n)
if pmax * pmax == n:
return pmax, pmax
bestp = 1
f = list(factors(n))
for t in uniq_powerset(f):
if 2 * len(t) > len(f):
break
p = np.prod(t) if t else 1
q = n // p
if p > q:
p, q = q, p
if p > bestp:
bestp = p
return bestp, n // bestp
例如:
>>> squarishrt(500)
20, 25
您可以直接使用它来重塑形状,例如:
a = np.arange(500)
b = a.reshape(squarishrt(len(a)))
>>> b.shape
20, 25
请注意,顺便说一句,对因素的贪婪搜索并不一定会产生最佳解决方案。例如:
>>> list(factors(500))
[2, 2, 5, 5, 5]
它们的最佳组合是
p = 2 * 2 * 5
(前三个因素)和q = 5 * 5
(后三个)。
相比之下:
>>> list(factors(300))
[2, 2, 3, 5, 5]
最接近平方的分解是
p = 3 * 5
和 q = 2 * 2 * 5
。