Commit d6b3bbaa authored by twanvl's avatar twanvl

Non-integer numeric values are sorted correctly in graphs

parent 050aa8bf
...@@ -22,7 +22,6 @@ DECLARE_TYPEOF_COLLECTION(vector<int>); ...@@ -22,7 +22,6 @@ DECLARE_TYPEOF_COLLECTION(vector<int>);
DECLARE_TYPEOF_COLLECTION(String); DECLARE_TYPEOF_COLLECTION(String);
DECLARE_TYPEOF_COLLECTION(UInt); DECLARE_TYPEOF_COLLECTION(UInt);
DECLARE_TYPEOF_COLLECTION(pair<String COMMA String>); DECLARE_TYPEOF_COLLECTION(pair<String COMMA String>);
DECLARE_TYPEOF(map<String COMMA UInt>);
template <typename T> inline T sgn(T v) { return v < 0 ? -1 : 1; } template <typename T> inline T sgn(T v) { return v < 0 ? -1 : 1; }
...@@ -30,6 +29,14 @@ template <typename T> inline T sgn(T v) { return v < 0 ? -1 : 1; } ...@@ -30,6 +29,14 @@ template <typename T> inline T sgn(T v) { return v < 0 ? -1 : 1; }
DEFINE_EVENT_TYPE(EVENT_GRAPH_SELECT); DEFINE_EVENT_TYPE(EVENT_GRAPH_SELECT);
// ----------------------------------------------------------------------------- : GraphAxis
void GraphAxis::addGroup(const String& name, UInt size) {
groups.push_back(GraphGroup(name, size));
max = std::max(max, size);
total += size;
}
// ----------------------------------------------------------------------------- : GraphData // ----------------------------------------------------------------------------- : GraphData
GraphElement::GraphElement(const String& v1) { GraphElement::GraphElement(const String& v1) {
...@@ -59,6 +66,11 @@ void GraphDataPre::splitList(size_t axis) { ...@@ -59,6 +66,11 @@ void GraphDataPre::splitList(size_t axis) {
} }
struct SmartLess{
inline operator () (const String& a, const String& b) const { return smart_less(a,b); }
};
DECLARE_TYPEOF(map<String COMMA UInt COMMA SmartLess>);
GraphData::GraphData(const GraphDataPre& d) GraphData::GraphData(const GraphDataPre& d)
: axes(d.axes) : axes(d.axes)
{ {
...@@ -67,11 +79,33 @@ GraphData::GraphData(const GraphDataPre& d) ...@@ -67,11 +79,33 @@ GraphData::GraphData(const GraphDataPre& d)
// find groups on each axis // find groups on each axis
size_t i = 0; size_t i = 0;
FOR_EACH(a, axes) { FOR_EACH(a, axes) {
map<String,UInt> counts; // note: default constructor for UInt() does initialize to 0 map<String,UInt,SmartLess> counts; // note: default constructor for UInt() does initialize to 0
FOR_EACH_CONST(e, d.elements) { FOR_EACH_CONST(e, d.elements) {
counts[e->values[i]] += 1; counts[e->values[i]] += 1;
} }
if (a->numeric) { if (a->numeric) {
// Add all values, calculate mean of the numeric ones
UInt numeric_count = 0;
int prev = 0;
FOR_EACH(c, counts) {
// numeric?
double d;
if (c.first.ToDouble(&d)) {
// update mean
a->mean += d * c.second;
numeric_count += c.second;
// add 0 bars before this value
int next = (int)floor(d);
for (int i = prev ; i < next ; i++) {
a->addGroup(String()<<i, 0);
}
prev = next + 1;
}
// add
a->addGroup(c.first, c.second);
}
a->mean /= numeric_count;
/*
// TODO: start at something other than 0? // TODO: start at something other than 0?
// TODO: support fractions? // TODO: support fractions?
a->mean = 0; a->mean = 0;
...@@ -82,17 +116,16 @@ GraphData::GraphData(const GraphDataPre& d) ...@@ -82,17 +116,16 @@ GraphData::GraphData(const GraphDataPre& d)
map<String,UInt>::const_iterator it = counts.find(is); map<String,UInt>::const_iterator it = counts.find(is);
if (it == counts.end()) { if (it == counts.end()) {
// not found, add a 0 bar // not found, add a 0 bar
a->groups.push_back(GraphGroup(is, 0)); a->addGroup(is, 0);
} else { } else {
a->groups.push_back(GraphGroup(is, it->second)); a->addGroup(is, it->second);
a->max = max(a->max, it->second);
a->total += it->second;
a->mean += i * it->second; a->mean += i * it->second;
counts.erase(is); counts.erase(is);
left--; left--;
} }
i++; i++;
} }
UInt numeric_count = a->total;
a->mean /= a->total; a->mean /= a->total;
// drop empty tail // drop empty tail
while (a->groups.size() > 1 && a->groups.back().size == 0) { while (a->groups.size() > 1 && a->groups.back().size == 0) {
...@@ -100,23 +133,17 @@ GraphData::GraphData(const GraphDataPre& d) ...@@ -100,23 +133,17 @@ GraphData::GraphData(const GraphDataPre& d)
} }
// Also keep non-numeric entries // Also keep non-numeric entries
FOR_EACH(c, counts) { FOR_EACH(c, counts) {
a->groups.push_back(GraphGroup(c.first, c.second)); a->addGroup(c.first, c.second);
a->max = max(a->max, c.second);
a->total += c.second;
} }
*/
} else if (a->order) { } else if (a->order) {
// specific group order // specific group order
FOR_EACH_CONST(gn, *a->order) { FOR_EACH_CONST(gn, *a->order) {
UInt count = counts[gn]; a->addGroup(gn, counts[gn]);
a->groups.push_back(GraphGroup(gn, count));
a->max = max(a->max, count);
a->total += count;
} }
} else { } else {
FOR_EACH(c, counts) { FOR_EACH(c, counts) {
a->groups.push_back(GraphGroup(c.first, c.second)); a->addGroup(c.first, c.second);
a->max = max(a->max, c.second);
a->total += c.second;
} }
} }
// colors // colors
......
...@@ -72,6 +72,9 @@ class GraphAxis : public IntrusivePtrBase<GraphAxis> { ...@@ -72,6 +72,9 @@ class GraphAxis : public IntrusivePtrBase<GraphAxis> {
double mean; ///< Mean value, only for numeric axes double mean; ///< Mean value, only for numeric axes
const map<String,Color>* colors; ///< Colors for each choice (optional) const map<String,Color>* colors; ///< Colors for each choice (optional)
const vector<String>* order; ///< Order of the items (optional) const vector<String>* order; ///< Order of the items (optional)
/// Add a graph group
void addGroup(const String& name, UInt size);
}; };
/// A single data point of a graph /// A single data point of a graph
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment