所有
在回顾了StackOverflow和更广泛的互联网之后,我仍然在努力有效使用LINQ计算百分位数。
其中percentile是统计中使用的度量,表示一组观察值中观察到的给定百分比下降的值。下面的示例尝试将值列表转换为数组,其中每个(唯一)值表示为关联百分位数。 列表的min()和max()必须是返回的数组百分位数的0%和100%。
使用LINQPad,以下代码生成所需的输出VP []:
这可以解释为: - 在0%时,最小值为1 - 在100%时,最大值为3 - 在最小值和最大值之间的50%处,值为2
void Main()
{
var list = new List<double> {1,2,3};
double denominator = list.Count - 1;
var answer = list.Select(x => new VP
{
Value = x,
Percentile = list.Count(y => x > y) / denominator
})
//.GroupBy(grp => grp.Value) --> commented out until attempted duplicate solution
.ToArray();
answer.Dump();
}
public struct VP
{
public double Value;
public double Percentile;
}
然而,当&#34; list&#34;时,这会返回错误的VP []。包含重复的条目(例如1,2,** 2,** 3):
我尝试按列表中的唯一值进行分组(通过包含&#34; .GroupBy(grp =&gt; grp.Value)&#34;)未能产生所需的结果(值= 2,&amp;百分位数= 0.666):
欢迎所有建议。包括使用&#34; list.Count(y =&gt; x&gt; y)&#34;重复迭代,这是否是一种有效的方法。
一如既往,谢谢 香农
答案 0 :(得分:1)
我不确定我理解这个问题的要求。当我运行接受的答案的代码时,我得到了这个结果:
但如果我将输入更改为:
var dataSet = new List<double> { 1, 1, 1, 1, 2, 3, 3, 3, 2 };
...然后我得到了这个结果:
使用行“列表的min()和max()必须是返回的数组百分位数的0%和100%。”在我看来,OP要求的值从0到1,但更新的结果超过了1。
我觉得第一个值应该是0%似乎也不对,因为我不确定这对数据的意义是什么。
在阅读链接的维基百科页面后,似乎OP实际上正在尝试进行反向计算以计算百分位数值。事实上,文章说0的百分位是未定义的。这是有道理的,因为0的百分位数将是空值集 - 并且空集的最大值是多少?
OP似乎是从价值计算百分位数。因此,从这个意义上说,并且知道0未定义,似乎最合适的计算值是等于或低于集合中每个不同值的值的百分比。
现在,如果我使用Microsoft的Reactive Framework Team的Interactive Extensions(NuGet“Ix-Main”),那么我可以运行此代码:
var dataSet = new List<double> { 1, 1, 1, 1, 2, 3, 3, 3, 2 };
var result =
dataSet
.GroupBy(x => x)
.Scan(
new VP()
{
Value = double.MinValue, Proportion = 0.0
},
(a, x) =>
new VP()
{
Value = x.Key,
Proportion = a.Proportion + (double)x.Count() / dataSet.Count
});
我得到了这个结果:
这告诉我大约44%的值是1;大约67%的值是1或2; 100%的值为1,2或3。
在我看来,这是最符合要求的逻辑计算。
答案 1 :(得分:0)
void Main()
{
var list = new List<double> {1,2,3};
double denominator = list.Count - 1;
var answer = list.OrderBy(x => x).Select(x => new VP
{
Value = x,
Proportion = list.IndexOf(x) / denominator
})
.ToArray();
answer.Dump();
}
public struct VP
{
public double Value;
public double Proportion;
}
答案 2 :(得分:0)
这就是我做的。我更改了一些变量名以使上下文更清晰。
var dataSet = new List<double> { 1, 2, 3, 2 };
double denominator = dataSet.Count - 1;
var uniqueValues = dataSet.Distinct();
var vp = dataSet.Select(value => new VP
{
Value = value,
Proportion = dataSet.Count(datum => value > datum) / denominator
});
var answer = uniqueValues.Select(u => new VP{
Value = u,
Proportion = vp.Where(v => v.Value == u).Select(x => x.Proportion).Sum()
});