package happy.research.cf;
import happy.coding.math.Stats;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
public class RatingUtils
{
protected final static StandardDeviation sd = new StandardDeviation();
/**
* to rating values array
*
* @param ratings
* the collection of ratings
* @return a double array with rating values
*/
public static List<Double> toRatings(Collection<Rating> ratings)
{
if (ratings == null) return null;
List<Double> rs = new ArrayList<>();
for (Rating r : ratings)
rs.add(r.getRating());
return rs;
}
public static synchronized double std(Collection<Rating> ratings)
{
if (ratings == null || ratings.size() < 1) return Double.NaN;
List<Double> values = toRatings(ratings);
return Stats.sd(values);
}
public static double meanDistance(Map<String, Rating> ratings, Map<String, Double> itemMeanMap)
{
if (ratings == null || ratings.size() < 1) return Double.NaN;
double sum = 0.0;
double distance = 0.0;
int count = 0;
for (Rating r : ratings.values())
{
String item = r.getItemId();
double mean = itemMeanMap.get(item);
distance = Math.abs(r.getRating() - mean);
sum += distance;
count++;
}
return sum / count;
}
public static double mean(Collection<Rating> ratings)
{
double sum = 0.0;
for (Rating r : ratings)
sum += r.getRating();
return sum / ratings.size();
}
public static double mean(Map<String, Rating> ratings, Rating testRating)
{
double sum = 0.0;
int count = 0;
for (Entry<String, Rating> r : ratings.entrySet())
{
if (testRating != null)
{
String user = r.getValue().getUserId();
String item = r.getValue().getItemId();
if (testRating.getUserId().equals(user) && testRating.getItemId().equals(item)) continue;
}
count++;
sum += r.getValue().getRating();
}
return sum / count;
}
public static double mean(Map<String, Map<String, Rating>> userRatingsMap)
{
double sum = 0.0;
for (Map<String, Rating> rs : userRatingsMap.values())
{
double userSum = 0.0;
for (Rating r : rs.values())
userSum += r.getRating();
double userMean = userSum / rs.size();
sum += userMean;
}
return sum / userRatingsMap.size();
}
public static Map<String, Double> itemMeans(Map<String, Map<String, Rating>> itemRatingsMap)
{
Map<String, Double> map = new HashMap<>();
for (Entry<String, Map<String, Rating>> en : itemRatingsMap.entrySet())
{
String item = en.getKey();
Map<String, Rating> ratings = en.getValue();
double mean = Stats.mean(toRatings(ratings.values()));
if (Double.isNaN(mean)) continue;
map.put(item, mean);
}
return map;
}
}