Summarizing Bayesian rating formula - algorithm

Based on this url i found Bayesian Rating, which explains the rating model very well, i wanted to summarize the formula to make it much easier for anyone implementing an SQL statement. Would this be correct if i summarized the formula like this?
avg_num_votes = Sum(votes)/Count(votes) * Count(votes)
avg_rating = sum(votes)/count(votes)
this_num_votes = count(votes)
this_rating = Positive_votes - Negative_votes
Gath

It would look more like this:
avg_num_votes = Count(votes)/Count(items with at least 1 vote)
avg_rating = Sum(votes)/Count(items with at least 1 vote)
this_num_votes = Count(votes for this item)
this_rating = Sum(votes for this item)/Count(votes for this item)
If you are using a simple +/- system, Sum(votes) = Count(positive votes) (ie. treat + as 1, - as 0)
See also: Bayesian average.

Should the avg_rating not be:
Sum(votes)/Count(votes)
Yves

Related

Best way to get max value in LINQ?

I'm newbie to LINQ. I will like to get know what's the highest value for 'Date', which method is preferred?
var ma1x= spResult.Where(p =>p.InstrumentId== instrument).OrderByDescending(u => int.Parse(u.Date)).FirstOrDefault();
var max2= spResult.Where(p =>p.InstrumentId== instrument).Max(u => int.Parse(u.Date));
Max or OrderByDescending ?
Max is better for both the developer and the computer.
Max will be always better because Max is semantic and meaningful.
Enumerable.Max Method
Returns the maximum value in a sequence of values.
msdn
You want the max value? Use Max. You want to order? Use OrderBy. The next developer will thank you. To quote Martin Fowler:
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
If you really want to use OrderBy to do the role of Max at least, wrap the orderby and the first in a method with a meaningful name. Something like ... Max. Great, now you have a meaningful OrderBy.
Lets see how this custom Max will do.
Enumerable.Max should be O(n) in the worst case when OrderBy use a quicksort which is O(n^2). So, the custom max is worst than the standard one...
Enjoy the performance bonus and go for Enumerable.Max. It is better for both the developer and the computer.
Edit:
Check Marco's answer to see how they perform in practice. A race of horses is always a nice idea to know which one is the faster.
.Max() should be faster. First of all the semantics of the method are clearer and your colleagues will know what your call does.
I've compared both your options on the AdventureWorks2014 database, with the following calls in LinqPad:
var times = new List<long>();
for(var i = 0; i < 1000; i++) {
Stopwatch sw = Stopwatch.StartNew();
var max2= SalesOrderHeaders.Max(u => u.OrderDate);
long elapsed = sw.ElapsedMilliseconds;
times.Add(elapsed);
}
var averageElapsed = times.Sum (t => t) / times.Count();
averageElapsed.Dump(" ms");
Generated SQL:
SELECT MAX([t0].[OrderDate]) AS [value]
FROM [Sales].[SalesOrderHeader] AS [t0]
GO
Result:
5 ms
var times = new List<long>();
for(var i = 0; i < 1000; i++) {
Stopwatch sw = Stopwatch.StartNew();
var max1 = SalesOrderHeaders.OrderByDescending(u => u.OrderDate).FirstOrDefault();
long elapsed = sw.ElapsedMilliseconds;
times.Add(elapsed);
}
var averageElapsed = times.Sum (t => t) / times.Count();
averageElapsed.Dump(" ms");
Generated SQL:
SELECT TOP (1) [t0].[SalesOrderID], [t0].[RevisionNumber], [t0].[OrderDate], [t0].[DueDate], [t0].[ShipDate], [t0].[Status], [t0].[OnlineOrderFlag], [t0].[SalesOrderNumber], [t0].[PurchaseOrderNumber], [t0].[AccountNumber], [t0].[CustomerID], [t0].[SalesPersonID], [t0].[TerritoryID], [t0].[BillToAddressID], [t0].[ShipToAddressID], [t0].[ShipMethodID], [t0].[CreditCardID], [t0].[CreditCardApprovalCode], [t0].[CurrencyRateID], [t0].[SubTotal], [t0].[TaxAmt], [t0].[Freight], [t0].[TotalDue], [t0].[Comment], [t0].[rowguid] AS [Rowguid], [t0].[ModifiedDate]
FROM [Sales].[SalesOrderHeader] AS [t0]
ORDER BY [t0].[OrderDate] DESC
GO
Result:
28ms
Conclusion: Max() is more concise and faster!
Purely speculative, but I'd imagine max2. It is just looping through each item and checking if the value is higher than the last.
While max1 is checking which is higher and reordering. Even if it's just moving pointers around (rather than moving values), this is still more work.
The Max method is better than FirstOrDefault both of them send a result as true, but the performance of Max is good.
This code:
var ma1x= spResult.Where(p =>p.InstrumentId== instrument).OrderByDescending(u => int.Parse(u.Date)).FirstOrDefault();
First check you condition, then sort them order by your condition, after that will be select and have more action to find your result.

How to calculate original loan amount without year terms?

https://www.moneysmart.gov.au/tools-and-resources/calculators-and-apps/savings-goals-calculator
I want to get result like above calculator when I select:
I want to save: 6000
I want to spend it: As soon as possible
Starting balance: 0
Interest rate : 10%
Regular savings: 1000 Monthly
But I am getting not correct result using this code:
loan = 6000.0
interest = 10.0
monthly_payment = 1000.0
i =0.0
record = []
count = 1
add_interst = 0.0
while( loan>=0)
i = interest/(100*12)*loan
loan=i+(loan)-(monthly_payment);
add_interst = add_interst + i
end
puts add_interst
I am getting 181.42163384701658 which should be 168. I don't know where I am wrong.
The code doesn't work because you are doing the opposite of what the link you reference is doing. What they are calculating is saving interest, what you are calculating is loan interest.
Basically, this is how you should define the variables.Also, as others have pointed out, it is good to use BigDecimal to calculate money:
require 'bigdecimal'
balance = 0.to_d
interest = 10.to_d/1200.to_d
regular_saving = 1000;
goal =6000;
i = 0;
added_interest = 0
So, to correct things, you have to start from the starting balance (i.e 0) and start incrementing. Something like this:
while balance < goal
balance += regular_saving;
i = balance * (interest);
balance +=i;
added_interest+=i;
end
Note also, that in the last year you don't need to pay the full saving amount. You only need to pay to reach the goal. For that, you need to add a conditional statement to check goal - balance < regular_saving. If this was the case, the interest should be calculated in terms of the balance that should be paid (slightly less than the goal).

Linq to Entities Percentages

Does anyone have any tips for calculating percentages in Linq to Entities?
I'm guessing that there must be a more efficient way than returning 2 results and calculating in memory. Perhaps an inventive use of let or into?
EDIT
Thanks Mark for your comment, here is a code snippet, but I think this will result in 2 database hits:
int passed = (from lpt in this.PushedLearnings.Select(pl => pl.LearningPlanTask)
where lpt.OnlineCourseScores.Any(score => score.ActualScore >= ((lpt.LearningResource.PassMarkPercentage != (decimal?)null) ?lpt.LearningResource.PassMarkPercentage : 80))
select lpt).Count();
int total = (from lpt in this.PushedLearnings.Select(pl => pl.LearningPlanTask)
select lpt).Count();
double percentage = passed * 100 / total;
If you use LINQ to Entities and write something along the lines of select x * 100.0 / y in your query then this expression will be converted to SQL and run in the database. It will be efficient.

LINQ get max of Amount but return name

I have 2 columns
Name and Amount
I like the linq to return the Name based on who has the Maximum Amount.
So far I have the following:
string name = (from nm in bg
select nm.Name).Max(Amount);
which obviously will not work.
Thank you.
string name = (from nm in bg
where nm.Amount == bg.Max(i=>i.Amount)
select nm.Name)
or
string name = (from nm in bg
orderby nm.Amount desc
select nm.Name).First()
Fastest approach I can think is as this (find max amount, then find item which has max amount, two way traversing, and is O(n)):
decimal amount = bg.Max(x=>x.Amount);
var name = bg.First(x=>x.Amount == amount).Name; // O(n)
Also you can do:
// O(n^2) in worst case, O(n) in best case
bg.First(x=>x.Amount == bg.Max(x=>x.Amount)).Name;
Or
bg.OrderByDescending(x=>x.Amount).First().Name; // O(n log n) in all situation
The expression
bg.OrderByDescending(nm => nm.Amount).First().Name
will get what you want, but will throw if bg is empty. If this is a problem, use
var topNm = bg.OrderByDescending(nm => nm.Amount).FirstOrDefault();
and check topNm for nullity.

minimum value in dictionary using linq

I have a dictionary of type
Dictionary<DateTime,double> dictionary
How can I retrive a minimum value and key coresponding to this value from this dictionary using linq ?
var min = dictionary.OrderBy(kvp => kvp.Value).First();
var minKey = min.Key;
var minValue = min.Value;
This is not very efficient though; you might want to consider MoreLinq's MinBy extension method.
If you are performing this query very often, you might want to consider a different data-structure.
Aggregate
var minPair = dictionary.Aggregate((p1, p2) => (p1.Value < p2.Value) ? p1 : p2);
Using the mighty Aggregate method.
I know that MinBy is cleaner in this case, but with Aggregate you have more power and its built-in. ;)
Dictionary<DateTime, double> dictionary;
//...
double min = dictionary.Min(x => x.Value);
var minMatchingKVPs = dictionary.Where(x => x.Value == min);
You could combine it of course if you really felt like doing it on one line, but I think the above is easier to read.
var minMatchingKVPs = dictionary.Where(x => x.Value == dictionary.Min(y => y.Value));
You can't easily do this efficiently in normal LINQ - you can get the minimal value easily, but finding the key requires another scan through. If you can afford that, use Jess's answer.
However, you might want to have a look at MinBy in MoreLINQ which would let you write:
var pair = dictionary.MinBy(x => x.Value);
You'd then have the pair with both the key and the value in, after just a single scan.
EDIT: As Nappy says, MinBy is also in System.Interactive in Reactive Extensions.

Resources