diff --git a/docs/src/lib/functions.md b/docs/src/lib/functions.md index 62f57681c1..a3e154d2c1 100644 --- a/docs/src/lib/functions.md +++ b/docs/src/lib/functions.md @@ -99,6 +99,7 @@ filter filter! first last +only nonunique unique unique! diff --git a/src/DataFrames.jl b/src/DataFrames.jl index 35653e2129..6a8b7db008 100644 --- a/src/DataFrames.jl +++ b/src/DataFrames.jl @@ -80,6 +80,13 @@ if VERSION < v"1.2" export hasproperty end +if isdefined(Base, :only) # Introduced in 1.4.0 + import Base.only +else + import Compat.only + export only +end + include("other/utils.jl") include("other/index.jl") diff --git a/src/abstractdataframe/abstractdataframe.jl b/src/abstractdataframe/abstractdataframe.jl index ba7a68d76a..46aee96257 100644 --- a/src/abstractdataframe/abstractdataframe.jl +++ b/src/abstractdataframe/abstractdataframe.jl @@ -434,6 +434,16 @@ end ## ############################################################################## +""" + only(df::AbstractDataFrame) + +If `df` has a single row return it as a `DataFrameRow`; otherwise throw `ArgumentError`. +""" +function only(df::AbstractDataFrame) + nrow(df) != 1 && throw(ArgumentError("data frame must contain exactly 1 row")) + return df[1, :] +end + """ first(df::AbstractDataFrame) diff --git a/test/dataframe.jl b/test/dataframe.jl index 43bf72b450..dddc6ef28d 100644 --- a/test/dataframe.jl +++ b/test/dataframe.jl @@ -1051,7 +1051,7 @@ end @inferred ncol(df) end -@testset "description" begin +@testset "first, last and only" begin df = DataFrame(A = 1:10) @test first(df) == df[1, :] @@ -1063,6 +1063,11 @@ end @test first(df, 1) == DataFrame(A = 1) @test last(df, 6) == DataFrame(A = 5:10) @test last(df, 1) == DataFrame(A = 10) + + @test_throws ArgumentError only(df) + @test_throws ArgumentError only(DataFrame()) + df = DataFrame(a=1, b=2) + @test only(df) === df[1, :] end @testset "column conversions" begin