向量中最常见的术语 - 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
。
我觉得我在这里真的很愚蠢,因为我认为 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
。