Skip to content

Commit

Permalink
early work for skipna
Browse files Browse the repository at this point in the history
  • Loading branch information
samukweku committed Apr 20, 2023
1 parent 8e1d633 commit 0bc78d9
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 19 deletions.
1 change: 0 additions & 1 deletion src/core/expr/fexpr.cc
Expand Up @@ -543,7 +543,6 @@ DECLARE_METHOD(&PyFExpr::nth)
->name("nth")
->arg_names({"n", "skipna"})
->n_positional_or_keyword_args(2)
->n_required_args(1)
->docs(dt::doc_FExpr_nth);


Expand Down
97 changes: 81 additions & 16 deletions src/core/expr/fexpr_nth.cc
Expand Up @@ -20,16 +20,19 @@
// IN THE SOFTWARE.
//------------------------------------------------------------------------------
#include "column/const.h"
#include "column/func_binary.h"
#include "column/isna.h"
#include "column/nth.h"
#include "documentation.h"
#include "expr/fexpr_func.h"
#include "expr/eval_context.h"
#include "python/xargs.h"
#include <iostream>
namespace dt {
namespace expr {


template<bool SKIPNA>
template<size_t SKIPNA>
class FExpr_Nth : public FExpr_Func {
private:
ptrExpr arg_;
Expand All @@ -46,11 +49,57 @@ class FExpr_Nth : public FExpr_Func {
out += arg_->repr();
out += ", n=";
out += std::to_string(n_);
out += ", skipna=";
out += SKIPNA? "True" : "False";
if (SKIPNA == 0) {
out += ", skipna=None";
} else if (SKIPNA == 1) {
out += ", skipna=any";
} else if (SKIPNA == 2) {
out += ", skipna=all";
}
out += ')';
return out;
}

static Column make_isna_col(Column&& col) {
switch (col.stype()) {
case SType::VOID: return Const_ColumnImpl::make_bool_column(col.nrows(), true);
case SType::BOOL:
case SType::INT8: return Column(new Isna_ColumnImpl<int8_t>(std::move(col)));
case SType::INT16: return Column(new Isna_ColumnImpl<int16_t>(std::move(col)));
case SType::DATE32:
case SType::INT32: return Column(new Isna_ColumnImpl<int32_t>(std::move(col)));
case SType::TIME64:
case SType::INT64: return Column(new Isna_ColumnImpl<int64_t>(std::move(col)));
case SType::FLOAT32: return Column(new Isna_ColumnImpl<float>(std::move(col)));
case SType::FLOAT64: return Column(new Isna_ColumnImpl<double>(std::move(col)));
case SType::STR32:
case SType::STR64: return Column(new Isna_ColumnImpl<CString>(std::move(col)));
default: throw RuntimeError();
}
}

template<typename T>
static Column make_bool_col(Column&& a, Column&& b, SType BOOL) {
xassert(compatible_type<T>(stype));
size_t nrows = a.nrows();
a.cast_inplace(SType::BOOL);
b.cast_inplace(SType::BOOL);
if (SKIPNA == 1) {
return Column(new FuncBinary1_ColumnImpl<T, T, T>(
std::move(a), std::move(b),
[](T x, T y){ return x | y; },
nrows, SType::BOOL
));
}
if (SKIPNA == 2) {
return Column(new FuncBinary1_ColumnImpl<T, T, T>(
std::move(a), std::move(b),
[](T x, T y){ return x & y; },
nrows, SType::BOOL
));
}

}


Workframe evaluate_n(EvalContext &ctx) const override {
Expand All @@ -67,16 +116,12 @@ class FExpr_Nth : public FExpr_Func {
);
Column coli = evaluate1(wf.retrieve_column(i), gby, is_grouped, n_);
outputs.add_column(std::move(coli), wf.retrieve_name(i), Grouping::GtoONE);
// auto coli = inputs.retrieve_column(i);
// outputs.add_column(
// evaluate1(std::move(coli), gby, n_),
// inputs.retrieve_name(i),
// Grouping::GtoONE
// );
}
return outputs;
}




Column evaluate1(Column&& col, const Groupby& gby, bool is_grouped, const int32_t n) const {
SType stype = col.stype();
Expand Down Expand Up @@ -111,17 +156,37 @@ class FExpr_Nth : public FExpr_Func {
static py::oobj pyfn_nth(const py::XArgs& args) {
auto arg = args[0].to_oobj();
auto n = args[1].to<py::oobj>(py::oint(0));
auto skipna = args[2].to<bool>(false);
auto skipna = args[2].to_oobj_or_none();
if (!skipna.is_none()) {
if (!skipna.is_string()) {
throw TypeError() << "The argument for the `skipna` parameter "
<<"in function datatable.nth() should either be None, "
<<"or a string, instead got "<<skipna.typeobj();

}
std::string skip_na = skipna.to_string();
if (skip_na != "any" && skip_na != "all") {
throw TypeError() << "The argument for the `skipna` parameter "
<<"in function datatable.nth() should either be None, "
<<"any or all, instead got "<<skipna.repr();
}
}
if (!n.is_int()) {
throw TypeError() << "The argument for the `nth` parameter "
<<"in function datatable.nth() should be an integer, "
<<"instead got "<<n.typeobj();
}
if (skipna) {
return PyFExpr::make(new FExpr_Nth<true>(as_fexpr(arg), n));
} else {
return PyFExpr::make(new FExpr_Nth<false>(as_fexpr(arg), n));
}
if (!skipna.is_none()) {
std::string skip_na = skipna.to_string();
if (skip_na == "any") {
return PyFExpr::make(new FExpr_Nth<1>(as_fexpr(arg), n));
}
if (skip_na == "all") {
return PyFExpr::make(new FExpr_Nth<2>(as_fexpr(arg), n));
}

}
return PyFExpr::make(new FExpr_Nth<0>(as_fexpr(arg), n));
}


Expand All @@ -131,7 +196,7 @@ DECLARE_PYFN(&pyfn_nth)
->arg_names({"cols", "n", "skipna"})
->n_positional_args(1)
->n_positional_or_keyword_args(2)
->n_required_args(2);
->n_required_args(1);


}} // dt::expr
2 changes: 0 additions & 2 deletions src/core/expr/head_reduce_unary.cc
Expand Up @@ -723,8 +723,6 @@ Workframe Head_Reduce_Unary::evaluate_n(
} else {
switch (op) {
case Op::STDEV: fn = compute_gsd; break;
case Op::FIRST:
case Op::LAST: fn = compute_gfirstlast; break;
case Op::MIN:
case Op::MAX:
case Op::FIRST:
Expand Down

0 comments on commit 0bc78d9

Please sign in to comment.