Skip to content

Commit

Permalink
tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pdeffebach committed Feb 20, 2024
1 parent 5afe511 commit 1d33e61
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/DataFramesMeta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export @with,
@distinct, @rdistinct, @distinct!, @rdistinct!,
@eachrow, @eachrow!,
@byrow, @passmissing, @astable, @kwarg,
@addlabel, @addnote,
@label!, @note!,
@based_on, @where # deprecated

const DOLLAR = raw"$"
Expand Down
109 changes: 97 additions & 12 deletions src/metadata.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ end
function addlabel_helper(df, args...)
x, exprs, outer_flags, kw = get_df_args_kwargs(df, args...; wrap_byrow = false)
x_sym = gensym()
t = map(args) do e
t = map(exprs) do e
lhs, rhs = get_lhs_rhs(e)
:($label!($x_sym, $lhs, $rhs))
end
Expand All @@ -30,20 +30,63 @@ function addlabel_helper(df, args...)
end

"""
label(df, args...)
label!(df, args...)
Shorthand for `label!(df, ...)`
Assign labels to columns in a data frame using `:col = label` syntax.
Shorthand for `label!(df, ...)` from TablesMetaDataTools.jl.
```julia-repl
julia> df = DataFrame(wage = 12);
julia> @label! df :wage = "Wage per hour (USD)";
julia> printlabels(df)
┌────────┬─────────────────────┐
│ Column │ Label │
├────────┼─────────────────────┤
│ wage │ Wage per hour (USD) │
└────────┴─────────────────────┘
```
Use `@label!` for short descriptions, primarily for pretty printing.
Use `@note!` for longer explanations of columns.
Labels are "note"-style columnar metadata. Labels are preserved upon
renaming and transformations. `@label! :x = "Lab"` over-writes any
existing label for the column `:x`. To add information, see [`@note`](@ref).
`@label!` returns the input data frame for use with `@chain`.
Like other DataFramesMeta.jl macros, `@label!` can be used in "keyword"
format as well as block format.
```julia-repl
julia> df = DataFrame(wage = 12, tenure = 4);
julia> @label! df begin
:wage = "Wage per hour (USD)"
:tenure = "Tenure at job (months)"
end;
julia> printlabels(df)
┌────────┬────────────────────────┐
│ Column │ Label │
├────────┼────────────────────────┤
│ wage │ Wage per hour (USD) │
│ tenure │ Tenure at job (months) │
└────────┴────────────────────────┘
```
"""
macro addlabel(df, args...)
macro label!(df, args...)
esc(addlabel_helper(df, args...))
end

function addnote_helper(df, args...)
x, exprs, outer_flags, kw = get_df_args_kwargs(df, args...; wrap_byrow = false)
x_sym = gensym()
t = map(args) do e
t = map(exprs) do e
lhs, rhs = get_lhs_rhs(e)
:($note!($x_sym, $lhs, $rhs; append = true))
:($note!($x_sym, $lhs, string($rhs); append = true))
end
labblock = Expr(:block, t...)
quote
Expand All @@ -53,25 +96,67 @@ function addnote_helper(df, args...)
end
end

macro addnote(df, args...)
"""
note!(df, args...)
Assign notes to columns in a data frame using `:col = note` syntax.
Shorthand for `note!(df, col, note)` from TablesMetadataTools.jl.
Use `@note!` for longer explanations of columns.
Use `@label!` for short descriptions, primarily for pretty printing.
```julia-repl
julia> df = DataFrame(wage = 12);
julia> @note! df :wage = "
Long discussion of variable construction.
";
julia> printnotes(df)
Column: wage
────────────
Long discussion of variable construction.
```
Unlike labels, notes are appended.
```julia-repl
julia> @note! df :wage = "Another comment on variable construction";
julia> printnotes(df)
Column: wage
────────────
Wage per hour in 2014 USD taken from ACS data provided by IPUMS.
Wage per hour is measured directly for hourly workers. For
salaried workers, equal to salary / hours worked.
Values capped at the 99th percentile
```
"""
macro note!(df, args...)
esc(addnote_helper(df, args...))
end

function printlabels(df)
function printlabels(df; all = true)
d = colmetadata(df)
t = DataFrame(Column = names(df))
t.Label = labels(df)
if all == false
t = t[t.Label .!= t.Column, :]
end
pretty_table(t; show_subheader = false)
return nothing
end

function printnotes(df)
# "Column: " has 8 characters
L = maximum(length.(names(df))) + 8
for n in names(df)
println("Column: $n")
println(repeat("=", L))
nt = note(df, n)
println(nt)
println()
if nt != ""
println("Column: $n")
println(repeat("", L))
println(nt)
end
end
end
58 changes: 58 additions & 0 deletions test/metadata.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
module TestMetaData

using Test

@testset "labels" begin
df = DataFrame(a = 1, b = 2)
@label! df :a = "alab"
@test labels(df) == ["alab", "b"]

df = DataFrame(a = 1, b = 2)
@label! df begin
:a = "alab"
:b = "blab"
end
@test labels(df) == ["alab", "blab"]

df_new = leftjoin(DataFrame(a = 1, c = 2), df, on = :a)
@test labels(df_new) == ["a", "c", "blab"]

df_new = @rename df :a2 = :a
@test labels(df_new) == ["alab", "blab"]

df_new = @rtransform df :a = :a + 1
@test labels(df_new) == ["alab", "blab"]
end

@testset "notes" begin
df = DataFrame(a = 1, b = 2)
@note! df :a = "anote"
@test note(df, :a) == "anote"

@note! df :a = "anote2"
@test note(df, :a) == "anote\nanote2"

df = DataFrame(a = 1, b = 2)
@note! df begin
:a = "anote"
:b = "bnote"
end
@test note(df, :a) == "anote"
@test note(df, :b) == "bnote"

df_new = leftjoin(DataFrame(a = 1, c = 2), df, on = :a)
@test note(df_new, :a) == ""
@test note(df_new, :b) == "bnote"

df_new = @rename df :a2 = :a
@test note(df_new, :a2) == "anote"
@test note(df_new, :b) == "bnote"

df_new = @rtransform df :a = :a + 1
@test note(df_new, :a) == "anote"
@test note(df_new, :b) == "bnote"
end



end # module

0 comments on commit 1d33e61

Please sign in to comment.