问题描述
我觉得我在这里真的很愚蠢,因为我原以为 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
。