I'm removing outliers from a set of data using the method described here.
The method removes the outliers and returns the quartile values of the set after all outliers have been removed.
(Quartiles
is a class I wrote with properties for Q1
, Q2
, Q3
, and the Inter-quartile range, IQR
. The .Quartiles()
returns these values for a sequence of decimals.)
public Quartiles RemoveOutliers(ICollection<MyObject> objects)
{
if (objects.Count == 0)
{
return new Quartiles();
}
// Calculate Mean value of the set.
decimal meanValue = objects.Average(o => o.MyProperty);
// Find the Object whose value is farthest from the Mean.
MyObject objectFarthestFromMean = objects.OrderByDescending(o => Math.Abs(o.MyProperty - meanValue)).First();
Quartiles quartiles = objects.Quartiles(o => o.MyProperty);
// Remove Object if its value is more than 1.5*IQR from the Mean.
decimal minValue = meanValue - (1.5m * quartiles.IQR);
decimal maxValue = meanValue + (1.5m * quartiles.IQR);
if ((objectFarthestFromMean.MyProperty < minValue) || (objectFarthestFromMean.MyProperty > maxValue))
{
objects.Remove(objectFarthestFromMean);
return RemoveOutliers(objects);
}
// No outlier found, we're finished.
return quartiles;
}
Looking for any ways to improve or fix any pitfalls I haven't encountered in testing.
object.OrderByDescending(..)
besidesMyObject
andMyProperty
also indicate it's not real, am I right? \$\endgroup\$objects.OrderByDescending(...)
, though. Good catch. \$\endgroup\$