在PowerShell中查找数据集的统计模式

这个自我解答的问题是对this question的后续行动:

如何确定给定数据集的(数组)statistical mode,即最经常出现的一个值或一组值?

例如,在数组1,2,3,4,5中,有两种模式24,因为它们是最频繁出现的值。

shiweialive 回答:在PowerShell中查找数据集的统计模式

结合使用Group-ObjectSort-ObjectForEach-Object

# Sample dataset.
$dataset = 1,2,3,4,5

do { # dummy loop to allow efficient termination of the pipeline
  $dataset | Group-Object | Sort-Object Count -Descending | 
    ForEach-Object -Begin { $topCount = 0 } -Process { 
      if ($_.Count -lt $topCount) { break } # No longer top occurrence count,exit
      $topCount = $_.Count # Store the occurrence count.
      $_.Group[0] # Output the input value represented by the group.
    }
} while ($false)

以上产生24,这是两种模式(值最频繁出现,在这种情况下,每次出现两次);模式按输入顺序返回。

注意:虽然此解决方案从概念上讲是简单明了的,但是可能需要考虑大型数据集的性能。请参见底部,了解对某些输入可能进行的优化。

说明:

  • Group-Object按相等性对所有输入进行分组。

  • Sort-Object -Descending按成员计数以降序对结果组进行排序(最频繁出现的输入排在最前面)。

  • ForEach-Object命令循环遍历已排序的组,并为出现次数(频率)最高的/所有组输出由每个代表的输入。

do循环的原因是,从PowerShell Core 7.0.0-preview.5开始,如果进一步处理,则没有 direct 方式退出管道。不再需要输入。

有一个longstanding feature request on GitHub为此添加支持。

解决方法是使用封闭的循环并使用break打破它。
注意:在没有封闭循环的管道中,不要使用breakcontinue,因为它会在封闭循环中查找调用堆栈并退出脚本(如果存在)没有。

通过对比,虽然可以在管道的return块内使用ForEach-Object ,但它只会跳到 next 输入项-它不会停止处理其他输入。


性能更好的解决方案:

如果输入元素统一为简单数字或字符串(而不是复杂对象),则可以进行优化:

  • Group-Object的{​​{1}}禁止收集每个组中的各个输入。

  • 每个组的-NoElement属性反映了分组值,但是作为 string 来体现,因此必须将其转换回其原始数据类型。

.Name
本文链接:https://www.f2er.com/3148943.html

大家都在问