diff --git a/src/convert.jl b/src/convert.jl index 276ba9b..0d6167e 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -25,7 +25,7 @@ isna(x::ComplexF64) = isna(real(x)) || isna(imag(x)) # convert R vector into Vector holding elements of type T # if force_missing is true, the result is always Vector{Union{T,Missing}}, # otherwise it's Vector{T} if `rv` doesn't contain NAs -function jlvec(::Type{T}, rv::RVEC, force_missing::Bool=true) where T +function jlvec(::Type{T}, rv::RVEC, force_missing::Bool=true) where T <: Number anyna = any(isna, rv.data) if force_missing || anyna res = convert(Vector{Union{T,Missing}}, rv.data) @@ -154,6 +154,11 @@ function jlvec(::Type{ZonedDateTime}, rv::RVEC, force_missing::Bool=true) return datetimes end +# generic vector conversion +function jlvec(::Type{T}, rv::RVEC, force_missing::Bool=true) where T + return sexp2julia.(rv.data) +end + function sexp2julia(rex::RSEXPREC) @warn "Conversion of $(typeof(rex)) to Julia is not implemented" return nothing @@ -188,10 +193,10 @@ function sexp2julia(rl::RList) DataFrame(Any[isa(col, RAltRep) ? sexp2julia(col) : jlvec(col, false) for col in rl.data], identifier.(names(rl)), makeunique=true) elseif hasnames(rl) - DictoVec(Any[sexp2julia(item) for item in rl.data], names(rl)) + DictoVec(jlvec(Any, rl), names(rl)) else # FIXME return DictoVec if forceDictoVec is on - map(sexp2julia, rl.data) + jlvec(Any, rl) end end diff --git a/test/RDA.jl b/test/RDA.jl index 9f63cf7..1f1fe7f 100644 --- a/test/RDA.jl +++ b/test/RDA.jl @@ -98,6 +98,21 @@ using RData @test f["x"] == f["y"] == ["a", "b", "c"] end + @testset "List of vectors (#82)" begin + f = load(joinpath(rdata_path, "list_of_vec.rda")) + @test f["listofvec"] isa Vector + @test length(f["listofvec"]) == 3 + @test isequal(f["listofvec"], [[1., 2., missing], [3., 4.], [5., 6., missing]]) + + @test f["namedlistofvec"] isa DictoVec + @test length(f["namedlistofvec"]) == 3 + @test f["namedlistofvec"].name2index == Dict("A"=>1, "B"=>3) + @test isequal(values(f["namedlistofvec"]), [[1., 2., missing], [3., 4.], [5., 6., missing]]) + + @test f["testdf"] isa DataFrame + @test nrow(f["testdf"]) == 3 + @test isequal(f["testdf"][!, "listascol"], [[1., 2., missing], [3., 4.], [5., 6., missing, 7.]]) + end end # for ver in ... @testset "Loading AltRep-containing RData files (version=3)" begin diff --git a/test/data_v2/list_of_vec.rda b/test/data_v2/list_of_vec.rda new file mode 100644 index 0000000..de72cc2 Binary files /dev/null and b/test/data_v2/list_of_vec.rda differ diff --git a/test/data_v3/list_of_vec.rda b/test/data_v3/list_of_vec.rda new file mode 100644 index 0000000..77b85fe Binary files /dev/null and b/test/data_v3/list_of_vec.rda differ diff --git a/test/generate_rda.R b/test/generate_rda.R index 54b50f6..ceb25cb 100644 --- a/test/generate_rda.R +++ b/test/generate_rda.R @@ -124,6 +124,14 @@ altrepnames_df <- as.data.frame(altrepnames_list) names(altrepnames_df) <- names(altrepnames_list) save(altrepnames_list, altrepnames_df, file=file.path("data_v3", "altrep_names.rda"), version=3) +# list of vectors variable and list of vectors column (for #82) +listofvec <- list(c(1, 2, NA), c(3, 4), c(5, 6, NA)) +namedlistofvec <- list(A=c(1, 2, NA), c(3, 4), B=c(5, 6, NA)) +testdf <- data.frame(a = c("a", "b", "c")) +testdf$listascol <- list(c(1, 2, NA), c(3, 4), c(5, 6, NA, 7)) +save(listofvec, namedlistofvec, testdf, file=file.path("data_v2", "list_of_vec.rda"), version=2) +save(listofvec, namedlistofvec, testdf, file=file.path("data_v3", "list_of_vec.rda"), version=3) + # generate files using each of the supported compression types df <- data.frame(num = c(1.1, 2.2)) rdata_path <- "data_v3"