Reputation: 15
I have the following array:
array = [{"student" => 1, "cost" => 2, "university" => 2, "room" => 2},
{"student" => 1, "cost" => 5, "university" => 2, "room" => 3},
{"student" => 1, "cost" => 1, "university" => 3, "room" => 1},
{"student" => 2, "cost" => 1, "university" => 1, "room" => 3},
{"student" => 2, "cost" => 2, "university" => 2, "room" => 2},
{"student" => 2, "cost" => 4, "university" => 1, "room" => 1}]
I want an array that only has the maximum value and the percentile 95
of "cost"
, i.e.,
array = [{"student" => 1, "cost_max" => 5, "university" => 2, "room" => 3, "cost_per95" => 4.7},
{"student" => 2, "cost_max" => 4, "university" => 1, "room" => 1, "cost_per95"=> 3.9}
I have applied this:
groupedmax = array.group_by {|h| h["student"]}
keysmax = groupedmax.keys
arrmax = keysmax.map {|k| [k, groupedmax[k].max_by {|h| h["cost"]}]}
table_max = arrmax.map { |ts| ts[1] }
# => [{"student"=>1, "cost"=>5, "university"=>2, "room"=>3},
# {"student"=>2, "cost"=>4, "university"=>1, "room"=>1}]
but I do not know how to add the percentile 95
to that array. A way to calculate percentile is:
def percentile(values, percentile)
values_sorted = values.sort
k = (percentile*(values_sorted.length-1)+1).floor - 1
f = (percentile*(values_sorted.length-1)+1).modulo(1)
return values_sorted[k] + (f * (values_sorted[k+1] - values_sorted[k]))
end
Attentive to your comments.
Upvotes: 0
Views: 201
Reputation: 110725
def doit(arr)
arr.group_by { |h| h["student"] }.
map do |_,a|
costs = a.map { |h| h['cost'] }
imax = costs.each_index.max_by { |i| costs[i] }
a[imax].merge('cost_per95'=>percentile(costs, 0.95).round(1))
end
end
doit array
#=> [{"student"=>1, "cost"=>5, "university"=>2, "room"=>3, "cost_per95"=>4.7},
# {"student"=>2, "cost"=>4, "university"=>1, "room"=>1, "cost_per95"=>3.9}]
array = [{"student" => 1, "cost" => 2, "university" => 2, "room" => 2},
{"student" => 1, "cost" => 5, "university" => 2, "room" => 3},
{"student" => 1, "cost" => 1, "university" => 3, "room" => 1},
{"student" => 2, "cost" => 1, "university" => 1, "room" => 3},
{"student" => 2, "cost" => 3, "university" => 2, "room" => 2},
{"student" => 2, "cost" => 4, "university" => 1, "room" => 1}]
#=> [{"student"=>1, "cost"=>5, "university"=>2, "room"=>3, "cost_per95"=>4.7},
# {"student"=>2, "cost"=>4, "university"=>1, "room"=>1, "cost_per95"=>3.9}]
Upvotes: 1
Reputation: 339
You can use merge
to add keys in that hash.
Try this,
table_max = arrmax.map { |ts| ts[1].merge("cost_per95": ts[1]["cost"] * 0.95) }
or you can try this to do all your calculations in just one line
array.group_by{ |x| x["student"] }.values.map{ |gp| gp.max_by{ |st| st["cost"] }.merge({ "cost_per95": "Your calculations" })}
Upvotes: 0