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

问题描述

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

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

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

我想要返回值 8 的东西。

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


与此密切相关,我希望此结果返回最常见的非零条目,而我查看的某些向量将 0 作为最常见的条目。例如:V = [ 0,5 ]。所以无论我在这里执行什么,我都想返回 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,3,4,6,8,8];
vecsort(counts_for(V1,8),[2],4)[1][1]
> 8

V2 = [0,5];
vecsort(counts_for(V2,5),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,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,8 ])
 %1 = 8
 ? most_frequent([x,x,Mod(1,3),[],[]])
 %2 = []
 ? most_frequent_non0([ 0,5 ])
 %3 = 5
 ? most_frequent_non0([x,[]])
 %4 = x

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