Skip to content

Commit

Permalink
Merge pull request #96 from TidierOrg/fix-and-or-vectorization
Browse files Browse the repository at this point in the history
Fixed auto-vectorization of `&&` and `||` and added docs.
  • Loading branch information
Karandeep Singh committed Apr 30, 2023
2 parents 8207d8a + 0c54966 commit 28bcb41
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 5 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Tidier.jl updates

## v0.7.5 - 2023-04-30
- Fixed bug to ensure that `&&` and `||` are auto-vectorized
- Added docstrings and examples to show different ways of filtering by multiple "and" conditions, including `&&`, `&`, and separating multiple expressions with commas.

## v0.7.4 - 2023-04-11
- Added `as_float()`, `as_integer()`, and `as_string()`

Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Tidier"
uuid = "f0413319-3358-4bb0-8e7c-0c83523a93bd"
authors = ["Karandeep Singh"]
version = "0.7.4"
version = "0.7.5"

[deps]
Chain = "8be319e6-bccf-4806-a6f7-6fae938471bc"
Expand Down
34 changes: 30 additions & 4 deletions docs/examples/UserGuide/filter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,36 @@ movies = dataset("ggplot2", "movies");
# Let’s take a look at the movies whose budget was more than average. We will select only the first 5 rows for the sake of brevity.

@chain movies begin
@mutate(Budget = Budget / 1_000_000)
@filter(Budget >= mean(skipmissing(Budget)))
@select(Title, Budget)
@slice(1:5)
@mutate(Budget = Budget / 1_000_000)
@filter(Budget >= mean(skipmissing(Budget)))
@select(Title, Budget)
@slice(1:5)
end

# Let's search for movies that have at least 200 votes and a rating of greater than or equal to 8. There are 3 ways you can specify an "and" condition inside of `Tidier.jl`.

## The first option is to use the short-circuiting `&&` operator as shown below. This is the preferred approach because the second expression is only evaluated (per element) if the first one is true.

@chain movies begin
@filter(Votes >= 200 && Rating >= 8)
@select(Title, Votes, Rating)
@slice(1:5)
end

## The second option is to use the bitwise `&` operator. However, there is a key difference in syntax. Because the `&` operator takes a higher operator precendence than `>=`, you have to wrap the `>=` expressions inside of parentheses to ensure that the expression is evaluated correctly.

@chain movies begin
@filter((Votes >= 200) & (Rating >= 8))
@select(Title, Votes, Rating)
@slice(1:5)
end

## Finally, for "and" conditions only, you can separate the expressions with commas, similar to the behavior of `filter()` in `tidyverse`.

@chain movies begin
@filter(Votes >= 200, Rating >= 8)
@select(Title, Votes, Rating)
@slice(1:5)
end

# Now let's see how to use `@filter()` with `in`. Here's an example with a tuple.
Expand Down
10 changes: 10 additions & 0 deletions src/docstrings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,16 @@ julia> @chain df begin
2 │ d 4 14
3 │ e 5 15
julia> @chain df begin
@filter(b >= 3 && c >= 14)
end
2×3 DataFrame
Row │ a b c
│ Char Int64 Int64
─────┼────────────────────
1 │ d 4 14
2 │ e 5 15
julia> @chain df begin
@filter(b in (1, 3))
end
Expand Down
3 changes: 3 additions & 0 deletions src/parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ function parse_autovec(tidy_expr::Union{Expr,Symbol})
fn_new = Symbol("." * string(fn))
return :($fn_new($(args...)))
end
elseif hasproperty(x, :head) && (x.head == :&& || x.head == :||)
x.head = Symbol("." * string(x.head))
return x
end
return x
end
Expand Down

0 comments on commit 28bcb41

Please sign in to comment.