【发布时间】:2016-01-26 18:41:10
【问题描述】:
我正在尝试编写一个百分位数函数,该函数将 2 个向量作为输入,1 个向量作为输出。输入向量 (Distr) 之一将是随机数的分布。另一个输入向量(测试)将是我想从 Distr 计算百分位数的值向量。输出将是一个向量(与 Tests 大小相同),它返回 Tests 中每个值的百分位数。
以下是我想要的示例:
Input Distr = {3, 5, 8, 12}
Input Tests = {4, 9}
Output Percentile = {0.375, 0.8125}
以下是我在 C++ 中的实现:
vector<double> Percentile(vector<double> Distr, vector<double> Tests)
{
double prevValue, nextValue;
vector<double> result;
unsigned distrSize = Distr.size();
std::sort(Distr.begin(), Distr.end());
for (vector<double>::iterator test = Tests.begin(); test != Tests.end(); test++)
{
if (*test <= Distr.front())
{
result.push_back((double) 1 / distrSize); // min percentile returned (not important)
}
else if (Distr.back() <= *test)
{
result.push_back(1); // max percentile returned (not important)
}
else
{
prevValue = Distr[0];
for (unsigned sortedDistrIdx = 1; sortedDistrIdx < distrSize; sortedDistrIdx++)
{
nextValue = Distr[sortedDistrIdx];
if (nextValue <= *test)
{
prevValue = nextValue;
}
else
{
// linear interpolation
result.push_back(((*test - prevValue) / (nextValue - prevValue) + sortedDistrIdx) / distrSize);
break;
}
}
}
}
return result;
}
Distr 和 Tests 的大小都可以在 2,000 到 30,000 之间。
是否有任何现有的库可以计算如上所示(或类似)的百分位数?如果不是,我怎样才能使上面的代码更快?
【问题讨论】:
-
如果您不使用
push_back而是预先分配所涉及的向量,这将有所帮助。 -
一种方法是通过引用获取您的输入参数。目前正在无缘无故地复制大向量。
-
@JonathanPotter 因为 Distr 已排序,通过引用获取它会修改输入。此外,当两者都很大时,复制的线性成本只是总时间的一小部分。
-
您说
Distr将是随机数的分布,但在您的示例中它是排序的,并且大多数答案假设 @ 987654325@ 已排序。请澄清Distr是否最初排序。从您的代码来看,它似乎没有排序,因为您首先对其进行了排序。请注意,这种类型很可能是总成本的主要贡献者。 -
了解
test是否可以假定为初始排序也会很有帮助。
标签: c++ vector percentile