SEXP mutate_grouped(const DataFrame& df, const LazyDots& dots) { LOG_VERBOSE << "checking zero rows"; // special 0 rows case if (df.nrows() == 0) { DataFrame res = mutate_not_grouped(df, dots); res.attr("vars") = df.attr("vars"); res.attr("class") = df.attr("class"); return Data(res).data(); } LOG_VERBOSE << "initializing proxy"; typedef GroupedCallProxy<Data, Subsets> Proxy; Data gdf(df); int nexpr = dots.size(); check_not_groups(dots, gdf); Proxy proxy(gdf); LOG_VERBOSE << "copying data to accumulator"; NamedListAccumulator<Data> accumulator; int ncolumns = df.size(); CharacterVector column_names = df.names(); for (int i=0; i<ncolumns; i++) { accumulator.set(Symbol(column_names[i]), df[i]); } LOG_VERBOSE << "processing " << nexpr << " variables"; List variables(nexpr); for (int i=0; i<nexpr; i++) { Rcpp::checkUserInterrupt(); const Lazy& lazy = dots[i]; Environment env = lazy.env(); Shield<SEXP> call_(lazy.expr()); SEXP call = call_; Symbol name = lazy.name(); proxy.set_env(env); LOG_VERBOSE << "processing " << CharacterVector(name); if (TYPEOF(call) == LANGSXP || TYPEOF(call) == SYMSXP) { proxy.set_call(call); boost::scoped_ptr<Gatherer> gather(gatherer<Data, Subsets>(proxy, gdf, name)); SEXP variable = variables[i] = gather->collect(); proxy.input(name, variable); accumulator.set(name, variable); } else if (Rf_length(call) == 1) { boost::scoped_ptr<Gatherer> gather(constant_gatherer(call, gdf.nrows())); SEXP variable = variables[i] = gather->collect(); proxy.input(name, variable); accumulator.set(name, variable); } else if (Rf_isNull(call)) { accumulator.rm(name); continue; } else { stop("cannot handle"); } } return structure_mutate(accumulator, df, df.attr("class")); }
SEXP mutate_not_grouped(DataFrame df, const LazyDots& dots) { int nexpr = dots.size(); int nrows = df.nrows(); NamedListAccumulator<DataFrame> accumulator; int nvars = df.size(); if (nvars) { CharacterVector df_names = df.names(); for (int i=0; i<nvars; i++) { accumulator.set(Symbol(df_names[i]), df[i]); } } CallProxy call_proxy(df); List results(nexpr); for (int i=0; i<nexpr; i++) { Rcpp::checkUserInterrupt(); const Lazy& lazy = dots[i]; Shield<SEXP> call_(lazy.expr()); SEXP call = call_; Symbol name = lazy.name(); Environment env = lazy.env(); call_proxy.set_env(env); if (TYPEOF(call) == SYMSXP) { if (call_proxy.has_variable(call)) { results[i] = call_proxy.get_variable(PRINTNAME(call)); } else { results[i] = shared_SEXP(env.find(CHAR(PRINTNAME(call)))); } } else if (TYPEOF(call) == LANGSXP) { call_proxy.set_call(call); results[i] = call_proxy.eval(); } else if (Rf_length(call) == 1) { boost::scoped_ptr<Gatherer> gather(constant_gatherer(call, nrows)); results[i] = gather->collect(); } else if (Rf_isNull(call)) { accumulator.rm(name); continue; } else { stop("cannot handle"); } check_supported_type(results[i], name.c_str()); if (Rf_inherits(results[i], "POSIXlt")) { stop("`mutate` does not support `POSIXlt` results"); } int n_res = Rf_length(results[i]); if (n_res == nrows) { // ok } else if (n_res == 1) { // recycle boost::scoped_ptr<Gatherer> gather(constant_gatherer(results[i] , df.nrows())); results[i] = gather->collect(); } else { stop("wrong result size (%d), expected %d or 1", n_res, nrows); } call_proxy.input(name, results[i]); accumulator.set(name, results[i]); } List res = structure_mutate(accumulator, df, classes_not_grouped()); return res; }
SEXP mutate_not_grouped(DataFrame df, const QuosureList& dots) { const int nexpr = dots.size(); const int nrows = df.nrows(); NamedListAccumulator<DataFrame> accumulator; const int nvars = df.size(); if (nvars) { CharacterVector df_names = df.names(); for (int i = 0; i < nvars; i++) { accumulator.set(df_names[i], df[i]); } } CallProxy call_proxy(df); List results(nexpr); for (int i = 0; i < nexpr; i++) { Rcpp::checkUserInterrupt(); const NamedQuosure& quosure = dots[i]; Shield<SEXP> call_(quosure.expr()); SEXP call = call_; SymbolString name = quosure.name(); Environment env = quosure.env(); call_proxy.set_env(env); if (TYPEOF(call) == SYMSXP) { SymbolString call_name = SymbolString(Symbol(call)); if (call_proxy.has_variable(call_name)) { results[i] = call_proxy.get_variable(call_name); } else { results[i] = shared_SEXP(env.find(call_name.get_string())); } } else if (TYPEOF(call) == LANGSXP) { call_proxy.set_call(call); results[i] = call_proxy.eval(); } else if (Rf_length(call) == 1) { boost::scoped_ptr<Gatherer> gather(constant_gatherer(call, nrows)); results[i] = gather->collect(); } else if (Rf_isNull(call)) { accumulator.rm(name); continue; } else { stop("cannot handle"); } if (Rf_inherits(results[i], "POSIXlt")) { stop("`mutate` does not support `POSIXlt` results"); } const int n_res = Rf_length(results[i]); check_supported_type(results[i], name); check_length(n_res, nrows, "the number of rows"); if (n_res == 1 && nrows != 1) { // recycle boost::scoped_ptr<Gatherer> gather(constant_gatherer(results[i], nrows)); results[i] = gather->collect(); } call_proxy.input(name, results[i]); accumulator.set(name, results[i]); } List res = structure_mutate(accumulator, df, classes_not_grouped()); return res; }