Skip to content

Instantly share code, notes, and snippets.

@hadley
Last active December 10, 2015 15:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hadley/4454601 to your computer and use it in GitHub Desktop.
Save hadley/4454601 to your computer and use it in GitHub Desktop.
class Bin {
public:
virtual int operator() (double val) const =0;
};
class BinFixed : public Bin {
double width_;
double origin_;
public:
BinFixed (double width, double origin = 0) {
width_ = width;
origin_ = origin;
}
int operator() (double val) const {
return (val - origin_) / width_;
}
};
class BinBreaks : public Bin {
NumericVector breaks_;
NumericVector::iterator breaks_it_, breaks_end_;
public:
BinBreaks (NumericVector breaks) {
breaks_ = breaks;
breaks_it_ = breaks.begin();
breaks_end_ = breaks.end();
}
int operator() (double val) const {
NumericVector::iterator
bin_it = std::upper_bound(breaks_it_, breaks_end_, val);
return std::distance(breaks_it_, bin_it);
}
};
std::vector<int> bin_bin(NumericVector x, const Bin& binner) {
int bin, nmissing = 0;
std::vector<int> out;
NumericVector::iterator x_it = x.begin(), x_end;
for(; x_it != x.end(); ++x_it) {
double val = *x_it;
if (ISNAN(val)) {
++nmissing;
} else {
bin = binner(val);
if (bin < 0) continue;
// Make sure there's enough space
if (bin >= out.size()) {
out.resize(bin + 1);
}
++out[bin];
}
}
// Put missing values in the last position
out.push_back(nmissing);
return out;
}
// [[Rcpp::export]]
std::vector<int> bin_bin_fixed(NumericVector x, double width, double origin = 0) {
const Bin& binner = BinFixed(width, origin);
return bin_bin(x, binner);
}
// [[Rcpp::export]]
std::vector<int> bin_bin_breaks(NumericVector x, NumericVector breaks) {
const Bin& binner = BinBreaks(breaks);
return bin_bin(x, binner);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment