Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions r/src/array_from_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,14 +351,19 @@ std::shared_ptr<Array> MakeFactorArrayImpl(Rcpp::IntegerVector_ factor,

std::shared_ptr<Array> MakeFactorArray(Rcpp::IntegerVector_ factor,
const std::shared_ptr<arrow::DataType>& type) {
SEXP levels = factor.attr("levels");
int n = Rf_length(levels);
if (n < 128) {
return MakeFactorArrayImpl<arrow::Int8Type>(factor, type);
} else if (n < 32768) {
return MakeFactorArrayImpl<arrow::Int16Type>(factor, type);
} else {
return MakeFactorArrayImpl<arrow::Int32Type>(factor, type);
const auto& dict_type = checked_cast<const arrow::DictionaryType&>(*type);
switch (dict_type.index_type()->id()) {
case Type::INT8:
return MakeFactorArrayImpl<arrow::Int8Type>(factor, type);
case Type::INT16:
return MakeFactorArrayImpl<arrow::Int16Type>(factor, type);
case Type::INT32:
return MakeFactorArrayImpl<arrow::Int32Type>(factor, type);
case Type::INT64:
return MakeFactorArrayImpl<arrow::Int64Type>(factor, type);
default:
Rcpp::stop(tfm::format("Cannot convert to dictionary with index_type %s",
dict_type.index_type()->ToString()));
}
}

Expand Down Expand Up @@ -1297,8 +1302,8 @@ bool CheckCompatibleFactor(SEXP obj, const std::shared_ptr<arrow::DataType>& typ
return false;
}

auto* dict_type = checked_cast<arrow::DictionaryType*>(type.get());
return dict_type->value_type()->Equals(utf8());
const auto& dict_type = checked_cast<const arrow::DictionaryType&>(*type);
return dict_type.value_type()->Equals(utf8());
}

arrow::Status CheckCompatibleStruct(SEXP obj,
Expand Down
1 change: 1 addition & 0 deletions r/src/array_to_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ class Converter_Dictionary : public Converter {
case Type::UINT16:
case Type::INT16:
case Type::INT32:
// TODO: also add int64, uint32, uint64 downcasts, if possible
break;
default:
Rcpp::stop("Cannot convert Dictionary Array of type `%s` to R",
Expand Down
16 changes: 16 additions & 0 deletions r/tests/testthat/test-Table.R
Original file line number Diff line number Diff line change
Expand Up @@ -321,3 +321,19 @@ test_that("Table handles null type (ARROW-7064)", {
tab <- Table$create(a = 1:10, n = vctrs::unspecified(10))
expect_equivalent(tab$schema, schema(a = int32(), n = null()))
})

test_that("Can create table with specific dictionary types", {
fact <- example_data[,"fct"]
int_types <- c(int8(), int16(), int32(), int64())
# TODO: test uint types when format allows
# uint_types <- c(uint8(), uint16(), uint32(), uint64())
for (i in int_types) {
sch <- schema(fct = dictionary(i, utf8()))
tab <- Table$create(fact, schema = sch)
expect_equal(sch, tab$schema)
if (i != int64()) {
# TODO: same downcast to int32 as we do for int64() type elsewhere
expect_identical(as.data.frame(tab), fact)
}
}
})