我觉得我在这里真的很愚蠢,因为我本以为Pari中已经有一个简单的命令了,或者写起来应该很简单,但我根本无法理解。
给定一个向量,比如V,它将有重复的条目,如何确定最常见的条目是什么?
例如,假设我们有:V = [ 0, 1, 2, 2, 3, 4, 6, 8, 8, 8 ]
我想要一个能返回值8的东西。
我知道vecsearch
之类的东西,但我不知道如何调整它才能使其工作?
与此密切相关,我希望此结果返回最常见的非零条目,并且我看到的一些向量将0作为最常见的条目。例如:V = [ 0, 0, 0, 0, 3, 3, 5 ]
。所以无论我在这里执行什么,我都希望返回3。我试着写一些可以去掉所有零项的东西,但又很吃力。
我特别尝试过的是:
rem( v ) = {
my( c );
while( c = vecsearch( v, 0 ); #c, v = vecextract( v, "^c" ) ); v
}
但CCD_ 4似乎不喜欢这种设置。
如果您可以确保所有元素都在某个固定范围内,那么只需使用PARI/GP代码进行计数排序就足够了,如下所示:
counts_for(v: t_VEC, lower: t_INT, upper: t_INT) = {
my(counts = vector(1+upper-lower));
for(i=1, #v, counts[1+v[i]-lower]++);
vector(#counts, i, [i-1, counts[i]])
};
V1 = [0, 1, 2, 2, 3, 4, 6, 8, 8, 8];
vecsort(counts_for(V1, 0, 8), [2], 4)[1][1]
> 8
V2 = [0, 0, 0, 0, 3, 3, 5];
vecsort(counts_for(V2, 0, 5), [2], 4)[1][1]
> 0
为了方便起见,您还可以实现以下快捷方式:
counts_for1(v: t_VEC) = {
counts_for(v, vecmin(v), vecmax(v))
};
most_frequent(v: t_VEC) = {
my(counts=counts_for1(v));
vecsort(counts, [2], 4)[1][1]
};
most_frequent(V1)
> 8
most_frequent(V2)
> 0
matreduce
在一个更通用的设置中提供了这一点:应用于对象的向量,它返回一个2列矩阵,其第一列包含不同的对象,第二列包含向量中的多重性。(函数有一个更通用的形式,采用多集的并集。(
most_frequent(v) = my(M = matreduce(v), [n] = matsize(M)); M[n, 1];
most_frequent_non0(v) =
{ my(M = matreduce(v), [n] = matsize(M), x = M[n, 1]);
if (x == 0, M[n - 1, 1], x);
}
? most_frequent([ 0, 1, 2, 2, 3, 4, 6, 8, 8, 8 ])
%1 = 8
? most_frequent([x, x, Mod(1,3), [], [], []])
%2 = []
? most_frequent_non0([ 0, 0, 0, 0, 3, 3, 5 ])
%3 = 5
? most_frequent_non0([x, x, Mod(1,3), [], [], []])
%4 = x
如果输入空向量,第一个函数将出错,如果没有非零条目,则第二个函数出错。第二个函数测试";0";使用x == 0
测试(我们在GP中有著名的[] == 0
(;为了获得更严格的语义,请在函数定义中使用x === 0
。