func NewYErrorer(low, high string, qf qframe.QFrame) (YErrorer, error) {
	lowFn, err := NewValueFunc(low, qf)
	if err != nil {
		return YErrorer{}, qerrors.Propagate("NewYErrorer", err)
	}
	highFn, err := NewValueFunc(high, qf)
	if err != nil {
		return YErrorer{}, qerrors.Propagate("NewYErrorer", err)
	}
	return YErrorer{low: lowFn, high: highFn}, nil
}
NewYErrorer returns a new YErrorer for the values in
column low and high of the QFrame. All columns must have
numeric types.
package qplot
import (
	"strconv"
	"github.com/tobgu/qframe"
	"github.com/tobgu/qframe/qerrors"
	"github.com/tobgu/qframe/types"
)
type LabelFunc func(i int) string
func LabelOfString(view qframe.StringView) LabelFunc {
	return func(i int) string {
		return *view.ItemAt(i)
	}
}
func LabelOfEnum(view qframe.EnumView) LabelFunc {
	return func(i int) string {
		return *view.ItemAt(i)
	}
}
func LabelOfFloat(fmt byte, view qframe.FloatView) LabelFunc {
	return func(i int) string {
		return strconv.FormatFloat(view.ItemAt(i), fmt, -1, 64)
	}
}
func LabelOfInt(view qframe.IntView) LabelFunc {
	return func(i int) string {
		return strconv.FormatInt(int64(view.ItemAt(i)), 64)
	}
}
func LabelOfBool(view qframe.BoolView) LabelFunc {
	return func(i int) string {
		return strconv.FormatBool(view.ItemAt(i))
	}
}
type Labeller struct {
	len int
	fn  LabelFunc
}
func (l Labeller) Label(i int) string { return l.fn(i) }
func NewLabeller(len int, fn LabelFunc) Labeller {
	return Labeller{len: len, fn: fn}
}
type XYLabeller struct {
	Labeller
	XYer
}
type ValueFunc func(i int) float64
func NewValueFunc(col string, qf qframe.QFrame) (ValueFunc, error) {
	if !isNumCol(col, qf) {
		return nil, qerrors.New("NewValueFunc", "Column %s is not a numeric value", col)
	}
	if !qf.Contains(col) {
		return nil, qerrors.New("NewValueFunc", "QFrame does not contain column %s", col)
	}
	switch qf.ColumnTypeMap()[col] {
	case types.Int:
		return ValueOfInt(qf.MustIntView(col)), nil
	case types.Float:
		return ValueOfFloat(qf.MustFloatView(col)), nil
	default:
		panic(qerrors.New("NewValueFunc", "forgot to support a new column type?"))
	}
}
func MustNewValueFunc(col string, qf qframe.QFrame) ValueFunc {
	fn, err := NewValueFunc(col, qf)
	if err != nil {
		panic(qerrors.Propagate("MustNewValueFunc", err))
	}
	return fn
}
func ValueOfInt(view qframe.IntView) ValueFunc {
	return func(i int) float64 {
		return float64(view.ItemAt(i))
	}
}
func ValueOfFloat(view qframe.FloatView) ValueFunc {
	return func(i int) float64 {
		return view.ItemAt(i)
	}
}
type Valuer struct {
	len int
	fn  ValueFunc
}
func (v Valuer) Len() int { return v.len }
func (v Valuer) Value(i int) float64 { return v.fn(i) }
func NewValuer(col string, qf qframe.QFrame) (Valuer, error) {
	fn, err := NewValueFunc(col, qf)
	if err != nil {
		return Valuer{}, err
	}
	return Valuer{len: qf.Len(), fn: fn}, nil
}
func MustNewValuer(col string, qf qframe.QFrame) Valuer {
	valuer, err := NewValuer(col, qf)
	if err != nil {
		panic(qerrors.Propagate("MustNewValuer", err))
	}
	return valuer
}
type XYer struct {
	len int
	xfn ValueFunc
	yfn ValueFunc
}
func (xy XYer) Len() int { return xy.len }
func (xy XYer) XY(i int) (float64, float64) { return xy.xfn(i), xy.yfn(i) }
func NewXYer(x, y string, qf qframe.QFrame) (XYer, error) {
	xvals, err := NewValueFunc(x, qf)
	if err != nil {
		return XYer{}, qerrors.Propagate("NewXYer", err)
	}
	yvals, err := NewValueFunc(y, qf)
	if err != nil {
		return XYer{}, qerrors.Propagate("NewXYer", err)
	}
	return XYer{len: qf.Len(), xfn: xvals, yfn: yvals}, nil
}
func MustNewXYer(x, y string, qf qframe.QFrame) XYer {
	xyer, err := NewXYer(x, y, qf)
	if err != nil {
		panic(qerrors.Propagate("MustNewXYer", err))
	}
	return xyer
}
type XYZer struct {
	len int
	xfn ValueFunc
	yfn ValueFunc
	zfn ValueFunc
}
func (xyz XYZer) Len() int { return xyz.len }
func (xyz XYZer) XYZ(i int) (float64, float64, float64) {
	return xyz.xfn(i), xyz.yfn(i), xyz.zfn(i)
}
func (xyz XYZer) XY(i int) (float64, float64) {
	return xyz.xfn(i), xyz.yfn(i)
}
func NewXYZer(x, y, z string, qf qframe.QFrame) (XYZer, error) {
	xvals, err := NewValueFunc(x, qf)
	if err != nil {
		return XYZer{}, qerrors.Propagate("NewXYZer", err)
	}
	yvals, err := NewValueFunc(y, qf)
	if err != nil {
		return XYZer{}, qerrors.Propagate("NewXYZer", err)
	}
	zvals, err := NewValueFunc(z, qf)
	if err != nil {
		return XYZer{}, qerrors.Propagate("NewXYZer", err)
	}
	return XYZer{len: qf.Len(), xfn: xvals, yfn: yvals, zfn: zvals}, nil
}
func MustNewXYZer(x, y, z string, qf qframe.QFrame) XYZer {
	xyzer, err := NewXYZer(x, y, z, qf)
	if err != nil {
		panic(qerrors.Propagate("MustNewXYZer", err))
	}
	return xyzer
}
type YErrorer struct {
	low  ValueFunc
	high ValueFunc
}
func (ye YErrorer) YError(i int) (float64, float64) { return ye.low(i), ye.high(i) }