diff --git a/NEWS.md b/NEWS.md index 22d2045f0..1d7fd3050 100644 --- a/NEWS.md +++ b/NEWS.md @@ -42,6 +42,9 @@ * Ensure that `allunique(::AbstractDataFrame, ::Any)` always gets interpreted as test for uniqueness of rows in the first positional argument ([#3434](https://github.com/JuliaData/DataFrames.jl/issues/3434)) +* Make sure that an empty vector of `Any` or of `AbstractVector` is treated as having + no columns when a data frame is being processed with `combine`/`select`/`transform`. + ([#3435](https://github.com/JuliaData/DataFrames.jl/issues/3435)) # DataFrames.jl v1.6.1 Release Notes diff --git a/src/abstractdataframe/selection.jl b/src/abstractdataframe/selection.jl index a90f1203d..81dae2da9 100644 --- a/src/abstractdataframe/selection.jl +++ b/src/abstractdataframe/selection.jl @@ -822,7 +822,12 @@ function select_transform!((nc,)::Ref{Any}, df::AbstractDataFrame, newdf::DataFr res = newres elseif !(res isa Union{AbstractDataFrame, NamedTuple, DataFrameRow, AbstractMatrix, Tables.AbstractRow}) - res = Tables.columntable(res) + if res isa Union{AbstractVector{Any}, AbstractVector{<:AbstractVector}} + @assert isempty(res) + res = DataFrame() + else + res = Tables.columntable(res) + end end end diff --git a/test/select.jl b/test/select.jl index 67f97df2f..3a8ad3b23 100644 --- a/test/select.jl +++ b/test/select.jl @@ -3024,4 +3024,22 @@ end @test_throws ArgumentError combine(gdf, :x => (x -> x[1] == 2 ? "x" : cr) => AsTable) end +@testset "empty vector" begin + df = DataFrame(a=1:3) + + @test_throws ArgumentError select(df, :a => (x -> Vector{Any}[])) + + for T in (Vector{Any}, Any, NamedTuple{(:x,),Tuple{Int64}}) + v = combine(df, :a => (x -> T[])).a_function + @test isempty(v) + @test eltype(v) === T + end + + @test size(combine(df, :a => (x -> Vector{Any}[]) => AsTable)) == (0, 0) + @test size(combine(df, :a => (x -> Any[]) => AsTable)) == (0, 0) + df2 = combine(df, :a => (x -> NamedTuple{(:x,),Tuple{Int64}}[]) => AsTable) + @test size(df2) == (0, 1) + @test eltype(df2.x) === Int +end + end # module