2014-11-04 78 views
2

這是我輸入:如何查找Ruby數組的異常值/整數散列?

[{name: 'John', age: 50}, {name: 'Bob', age: 50}, {name: 'Paul', age: 0}, {name: 'Alfred', age: 100}] 

我想找到極端的年齡,我希望能夠把作爲變量的極限應該如何理智是。所以,舉個例子,我想說我想找到10%的極端值。所以例如輸出將是這樣的:

# the extreme min values => [{name: 'Paul', age: 0}] 
# the extreme max values => [{name: 'Alfred', age: 100}] 

我該怎麼做?

我發現了一些在線資源可能會有所幫助,但老實說,我不能夠按照自己的例子:

http://sciruby.com/blog/2013/11/07/statistics-with-ruby-time-series-and-general-linear-models/ http://statsample.apsique.cl/Statsample/Graph/Boxplot.html

回答

3

這裏有一種方法。

1.Sort名單:

a = [{name: 'John', age: 50}, {name: 'Bob', age: 50}, {name: 'Paul', age: 0}, {name: 'Alfred', age: 100}] 
a = a.sort{|a,b| a['age'] <=> b['age']} 

2,第一個元素是目前最小的,最後一個是最大的。

min, max = a[0], a[-1] 

請注意,這可能不是最有效的方法來做到這一點,但對於小型陣列來說,這已經夠用了。

WRT您的敏感性,上述的方法的工作原理是通過百分比p元素陣列的長度L乘以產生升,然後除以二,並採取

[0..l-1] 

作爲下離羣值和

[L-(l-1), L-1] 

爲你的上離羣

編輯:樣例

L是數組的長度,p是你想要的異常值的比率。

l = (L*p)/2 

對於p=0.2, L=20,我們會想這四個離羣,兩個在最低和兩個上最大的一面。

l = (L*p)/2 = 2 

min = a[0..1] 
max = a[(L-(l-1), L-1] = a[(20-(2-1), 19] = a[19,19] 

注意,這表明有一個錯誤在我告訴你上面 - 最大可能應該是a[(L-l),(L-1)]代替。

+0

對不起,我沒聽懂。你可以添加一個例子嗎? '[L-(l-1),L-1]'? – ChristofferJoergensen 2014-11-04 22:30:27

+0

@ChristofferJoergensen參見上面的工作示例。 – mcfinnigan 2014-11-05 09:17:49

0

的起點,這是minmax方法:

min_val, max_val = [1, 3, 0, 9, 6].minmax # => [0, 9] 

如果你需要深入挖掘的對象找出它的價值,使用minmax_by

class Foo 
    attr_reader :i 
    def initialize(i) 
    @i = i 
    end 
end 

min_foo, max_foo = [1, 3, 0, 9, 6].map{ |n| Foo.new(n) }.minmax_by{ |foo| foo.i } 
# => [#<Foo:0x007fd6dc8630c0 @i=0>, #<Foo:0x007fd6dc863098 @i=9>] 
+0

但是,這隻返回2個對象,最低和最高,對不對?我需要找到極端的例如10%。 – ChristofferJoergensen 2014-11-04 23:09:08

+0

沒錯。這是做你需要的基礎,它不是一個完整的答案。你可以在此建立起來。 – 2014-11-05 07:08:13

0

假設arr是你的陣列的哈希。您想查找arr[i][:age]最大的那個數組的n值。你可以通過排序arr[i][:age]然後取最後的n元素來完成。但是,如果n只是arr.size的一小部分,找到並保存arr[i][:age]最大的那個可能會更快,請將其刪除並重復n-1次。

代碼

def top_n(arr, n) 
    ad = arr.dup 
    n.times.with_object([]) do |_,a| 
    j = ad.each_index.max_by { |i| ad[i][:age] } 
    a << ad[j] 
    ad.delete_at(j) 
    end 
end 

arr = [{name: 'John' , age: 50}, 
     {name: 'Bob' , age: 50}, 
     {name: 'Tina' , age: 80}, 
     {name: 'Paul' , age: 0}, 
     {name: 'Alfred', age: 100}] 

top_n(arr, 3) 
    #=> [{:name=>"Alfred", :age=>100}, 
    # {:name=>"Tina", :age=>80}, 
    # {:name=>"John", :age=>50}]