<commit_before>#include "rcppbridge.h"

#include <boost/foreach.hpp>
#include "../JASP-Common/base64.h"
#include <iomanip>

using namespace std;


RcppBridge* RcppBridge::_staticRef;

RcppBridge::RcppBridge()
{
	_staticRef = this;

	_rInside[".read.dataset.native"] = Rcpp::InternalFunction(&RcppBridge::readDataSetStatic);
	_rInside[".read.dataset.header.native"] = Rcpp::InternalFunction(&RcppBridge::readDataSetHeaderStatic);
	_rInside[".callback.native"] = Rcpp::InternalFunction(&RcppBridge::callbackStatic);

	_rInside["jasp.analyses"] = Rcpp::List();
	_rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"RJSONIO\"))");
	_rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"JASP\"))");
}

void RcppBridge::setDataSet(DataSet* dataSet)
{
	_dataSet = dataSet;
}

Json::Value RcppBridge::init(const string &name, const Json::Value &options)
{
	SEXP results;

	_rInside["name"] = name;
	_rInside["options.as.json.string"] = options.toStyledString();
	_rInside.parseEval("init(name=name, options.as.json.string=options.as.json.string)", results);

	string resultsAsString = Rcpp::as<string>(results);

	Json::Reader r;
	Json::Value json;
	r.parse(resultsAsString, json);

	return json;
}

Json::Value RcppBridge::run(const string &name, const Json::Value &options, boost::function<int (Json::Value)> callback)
{
	SEXP results;

	_callback = callback;

	_rInside["name"] = name;
	_rInside["options.as.json.string"] = options.toStyledString();
	_rInside.parseEval("run(name=name, options.as.json.string=options.as.json.string)", results);

	_callback = NULL;

	string resultsAsString = Rcpp::as<string>(results);

	Json::Reader r;
	Json::Value json;
	r.parse(resultsAsString, json);

	return json;
}

Rcpp::DataFrame RcppBridge::readDataSet(const std::map<std::string, Column::ColumnType> &columns)
{
	Rcpp::List list(columns.size());
	Rcpp::CharacterVector columnNames;

	int colNo = 0;

	typedef pair<const string, Column::ColumnType> ColumnInfo;

	BOOST_FOREACH(const ColumnInfo &columnInfo, columns)
	{
		(void)columns;
		string dot = ".";

		string columnName = columnInfo.first;

		string base64 = Base64::encode(dot, columnName);
		columnNames.push_back(base64);

		Column &column = _dataSet->columns().get(columnName);
		Column::ColumnType columnType = column.columnType();

		Column::ColumnType requestedType = columnInfo.second;
		if (requestedType == Column::ColumnTypeUnknown)
			requestedType = columnType;

		int rowCount = column.rowCount();
		int rowNo = 0;

		if (requestedType == Column::ColumnTypeScale)
		{
			if (columnType == Column::ColumnTypeScale)
			{
				Rcpp::NumericVector v(rowCount);

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;
					v[rowNo++] = value;
				}

				list[colNo++] = v;
			}
			else if (columnType == Column::ColumnTypeOrdinal || columnType == Column::ColumnTypeNominal)
			{
				Rcpp::IntegerVector v(rowCount);

				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					v[rowNo++] = column.actualFromRaw(value);
				}

				list[colNo++] = v;
			}
			else // columnType == Column::ColumnTypeNominalText
			{
				Rcpp::IntegerVector v(rowCount);

				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					v[rowNo++] = column.actualFromRaw(value);
				}

				makeFactor(v, column.labels());

				list[colNo++] = v;
			}
		}
		else // if (requestedType != Column::ColumnTypeScale)
		{
			bool ordinal = (requestedType == Column::ColumnTypeOrdinal);

			Rcpp::IntegerVector v(rowCount);

			if (columnType != Column::ColumnTypeScale)
			{
				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					v[rowNo++] = value + 1;
				}

				makeFactor(v, column.labels(), ordinal);
			}
			else
			{
				// scale to nominal or ordinal (doesn't really make sense, but we have to do something)

				set<int> uniqueValues;

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;
					int intValue = (int)(value * 1000);
					uniqueValues.insert(intValue);
				}

				int index = 0;
				map<int, int> valueToIndex;
				vector<string> labels;

				BOOST_FOREACH(int value, uniqueValues)<commit_msg>Fix to dataframe loading of ordinals with NAs<commit_after>#include "rcppbridge.h"

#include <boost/foreach.hpp>
#include "../JASP-Common/base64.h"
#include <iomanip>

using namespace std;


RcppBridge* RcppBridge::_staticRef;

RcppBridge::RcppBridge()
{
	_staticRef = this;

	_rInside[".read.dataset.native"] = Rcpp::InternalFunction(&RcppBridge::readDataSetStatic);
	_rInside[".read.dataset.header.native"] = Rcpp::InternalFunction(&RcppBridge::readDataSetHeaderStatic);
	_rInside[".callback.native"] = Rcpp::InternalFunction(&RcppBridge::callbackStatic);

	_rInside["jasp.analyses"] = Rcpp::List();
	_rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"RJSONIO\"))");
	_rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"JASP\"))");
}

void RcppBridge::setDataSet(DataSet* dataSet)
{
	_dataSet = dataSet;
}

Json::Value RcppBridge::init(const string &name, const Json::Value &options)
{
	SEXP results;

	_rInside["name"] = name;
	_rInside["options.as.json.string"] = options.toStyledString();
	_rInside.parseEval("init(name=name, options.as.json.string=options.as.json.string)", results);

	string resultsAsString = Rcpp::as<string>(results);

	Json::Reader r;
	Json::Value json;
	r.parse(resultsAsString, json);

	return json;
}

Json::Value RcppBridge::run(const string &name, const Json::Value &options, boost::function<int (Json::Value)> callback)
{
	SEXP results;

	_callback = callback;

	_rInside["name"] = name;
	_rInside["options.as.json.string"] = options.toStyledString();
	_rInside.parseEval("run(name=name, options.as.json.string=options.as.json.string)", results);

	_callback = NULL;

	string resultsAsString = Rcpp::as<string>(results);

	Json::Reader r;
	Json::Value json;
	r.parse(resultsAsString, json);

	return json;
}

Rcpp::DataFrame RcppBridge::readDataSet(const std::map<std::string, Column::ColumnType> &columns)
{
	Rcpp::List list(columns.size());
	Rcpp::CharacterVector columnNames;

	int colNo = 0;

	typedef pair<const string, Column::ColumnType> ColumnInfo;

	BOOST_FOREACH(const ColumnInfo &columnInfo, columns)
	{
		(void)columns;
		string dot = ".";

		string columnName = columnInfo.first;

		string base64 = Base64::encode(dot, columnName);
		columnNames.push_back(base64);

		Column &column = _dataSet->columns().get(columnName);
		Column::ColumnType columnType = column.columnType();

		Column::ColumnType requestedType = columnInfo.second;
		if (requestedType == Column::ColumnTypeUnknown)
			requestedType = columnType;

		int rowCount = column.rowCount();
		int rowNo = 0;

		if (requestedType == Column::ColumnTypeScale)
		{
			if (columnType == Column::ColumnTypeScale)
			{
				Rcpp::NumericVector v(rowCount);

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;
					v[rowNo++] = value;
				}

				list[colNo++] = v;
			}
			else if (columnType == Column::ColumnTypeOrdinal || columnType == Column::ColumnTypeNominal)
			{
				Rcpp::IntegerVector v(rowCount);

				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					v[rowNo++] = column.actualFromRaw(value);
				}

				list[colNo++] = v;
			}
			else // columnType == Column::ColumnTypeNominalText
			{
				Rcpp::IntegerVector v(rowCount);

				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					v[rowNo++] = column.actualFromRaw(value);
				}

				makeFactor(v, column.labels());

				list[colNo++] = v;
			}
		}
		else // if (requestedType != Column::ColumnTypeScale)
		{
			bool ordinal = (requestedType == Column::ColumnTypeOrdinal);

			Rcpp::IntegerVector v(rowCount);

			if (columnType != Column::ColumnTypeScale)
			{
				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					if (value == INT_MIN)
						v[rowNo++] = INT_MIN;
					else
						v[rowNo++] = value + 1;
				}

				makeFactor(v, column.labels(), ordinal);
			}
			else
			{
				// scale to nominal or ordinal (doesn't really make sense, but we have to do something)

				set<int> uniqueValues;

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;
					int intValue = (int)(value * 1000);
					uniqueValues.insert(intValue);
				}

				int index = 0;
				map<int, int> valueToIndex;
				vector<string> labels;

				BOOST_FOREACH(int value, uniqueValues)
{'fraction_non_alphanumeric': 0.14680648236415633, 'fraction_numerical': 0.0038131553860819827, 'mean_word_length': 4.554599602911979, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3188975', 'n_tokens_mistral': 3360, 'n_tokens_neox': 2802, 'n_words': 516}