diff --git a/NEWS.md b/NEWS.md index b67347f783..7170399fd8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -77,6 +77,8 @@ * fix a problem with `unstack` on empty data frame ([#2842](/~https://github.com/JuliaData/DataFrames.jl/issues/2842)) +* fix a problem with not specialized `Pair` arguments passed as transformations + ([#2889](/~https://github.com/JuliaData/DataFrames.jl/issues/2889)) # DataFrames.jl v1.2.2 Patch Release Notes diff --git a/src/abstractdataframe/selection.jl b/src/abstractdataframe/selection.jl index 08c6acda53..8eff567f01 100755 --- a/src/abstractdataframe/selection.jl +++ b/src/abstractdataframe/selection.jl @@ -182,6 +182,10 @@ end # add a method to funname defined in other/utils.jl funname(row::ByRow) = funname(row.fun) +make_pair_concrete(@nospecialize(x::Pair)) = + make_pair_concrete(x.first) => make_pair_concrete(x.second) +make_pair_concrete(@nospecialize(x)) = x + normalize_selection(idx::AbstractIndex, @nospecialize(sel), renamecols::Bool) = try idx[sel] @@ -1328,7 +1332,7 @@ function manipulate(df::DataFrame, @nospecialize(cs...); copycols::Bool, keeprow push!(cs_vec, v) end end - return _manipulate(df, Any[normalize_selection(index(df), c, renamecols) for c in cs_vec], + return _manipulate(df, Any[normalize_selection(index(df), make_pair_concrete(c), renamecols) for c in cs_vec], copycols, keeprows) end @@ -1418,7 +1422,8 @@ function manipulate(dfv::SubDataFrame, @nospecialize(args...); copycols::Bool, k push!(cs_vec, v) end end - return _manipulate(dfv, Any[normalize_selection(index(dfv), c, renamecols) for c in cs_vec], + return _manipulate(dfv, Any[normalize_selection(index(dfv), + make_pair_concrete(c), renamecols) for c in cs_vec], true, keeprows) else # we do not support transformations here @@ -1436,7 +1441,7 @@ function manipulate(dfv::SubDataFrame, @nospecialize(args...); copycols::Bool, k push!(seen_single_column, ind_idx) end else - newind = normalize_selection(index(dfv), ind, renamecols) + newind = normalize_selection(index(dfv), make_pair_concrete(ind), renamecols) if newind isa Pair throw(ArgumentError("transforming and renaming columns of a " * "SubDataFrame is not allowed when `copycols=false`")) diff --git a/src/groupeddataframe/splitapplycombine.jl b/src/groupeddataframe/splitapplycombine.jl index 7895d9ce3d..533670118a 100644 --- a/src/groupeddataframe/splitapplycombine.jl +++ b/src/groupeddataframe/splitapplycombine.jl @@ -62,7 +62,7 @@ function _combine_prepare_norm(gd::GroupedDataFrame, cs_norm = [] optional_transform = Bool[] for c in cs_vec - arg = normalize_selection(index(parent(gd)), c, renamecols) + arg = normalize_selection(index(parent(gd)), make_pair_concrete(c), renamecols) if arg isa AbstractVector{Int} for col_idx in arg push!(cs_norm, col_idx => identity => _names(gd)[col_idx]) diff --git a/test/select.jl b/test/select.jl index e598517968..627655f0e7 100644 --- a/test/select.jl +++ b/test/select.jl @@ -1678,4 +1678,18 @@ end @test select(df, :a => ByRow(f) => :a) == DataFrame(a=1:3) end +@testset "vectors of pairs with non-specific type are accepted" begin + df = DataFrame(x=[1,2,3]) + @test combine(df, [1 => length => :a, 1 => length => "b"]) == DataFrame(a=3, b=3) + @test combine(df, [:x => length => :a, 1 => :b]) == DataFrame(a=3, b=1:3) + gdf = groupby(df, :x) + @test combine(gdf, [1 => length => :a, 1 => length => "b"]) == DataFrame(x=1:3, a=1, b=1) + @test combine(gdf, [:x => length => :a, 1 => :b]) == DataFrame(x=1:3, a=1, b=1:3) + sdf = view(df, :, :) + @test select(sdf, [1 => length => :a, 1 => length => "b"]) == DataFrame(a=[3, 3, 3], b=[3, 3, 3]) + @test select(sdf, [:x => length => :a, 1 => :b]) == DataFrame(a=3, b=1:3) + @test_throws ArgumentError select(sdf, [1 => length => :a, 1 => length => "b"], copycols=false) + @test_throws ArgumentError select(sdf, [:x => length => :a, 1 => :b], copycols=false) +end + end # module