向量中最常见的术语 - PARI/GP

Most common term in a vector - PARI/GP

我觉得我在这里真的很愚蠢,因为我认为 Pari 中已经有一个简单的命令,或者写起来应该很简单,但我就是想不通。

给定一个向量,比如 V,它将有重复的条目,如何确定最常见的条目是什么?

例如,假设我们有: V = [ 0, 1, 2, 2, 3, 4, 6, 8, 8, 8 ]

我想要 return 值为 8 的东西。

我知道 vecsearch 之类的东西,但我看不出如何对其进行调整才能使其发挥作用?


与此密切相关,我希望此结果为 return 最常见的非零条目,而我查看的一些向量将 0 作为最常见的条目。例如:V = [ 0, 0, 0, 0, 3, 3, 5 ]。所以无论我在这里执行什么,我都想 return 3。 我尝试写一些可以删除所有零项的东西,但又一次挣扎。

我特别尝试过的是:

rem( v ) = {
my( c );
while( c = vecsearch( v, 0 ); #c, v = vecextract( v, "^c" ) ); v
}

但是vecextract似乎不​​喜欢这个设置。

如果你能保证所有的元素都在某个固定的范围内,那么用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 在更一般的设置中提供了这一点:应用于对象向量,它 returns 一个双列矩阵,其第一列包含不同的对象,第二列包含它们的多样性在向量中。 (该函数有一个更一般的形式,采用多重集的并集。)

 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

如果输入空向量,第一个函数将出错,如果没有非零条目,第二个函数将出错。第二个函数使用 x == 0 测试来测试“0”(我们在 GP 中有著名的 [] == 0);要获得更严格的语义,请在函数定义中使用 x === 0