Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent select() and rename() behavior #90

Closed
jmobrien opened this issue Apr 9, 2019 · 5 comments
Closed

Inconsistent select() and rename() behavior #90

jmobrien opened this issue Apr 9, 2019 · 5 comments
Labels
bug an unexpected problem or unintended behavior rename

Comments

@jmobrien
Copy link

jmobrien commented Apr 9, 2019

Passing a named list to select() performs select/rename behavior, but doing the same with rename() produces the confusing error "All arguments must be named"

It does work when "!!!" is applied, but I'm unclear what's different about the structure here, and the message doesn't really provide insight.

newnames <- c("Sepal.Length", "Petal.Length") %>% 
  setNames(c("Sepal_Length", "Petal_Length"))

iris %>% select(newnames) %>% names
iris %>% rename(newnames) %>% names

iris %>% select(!!!newnames) %>% names
iris %>% rename(!!!newnames) %>% names
@batpigandme
Copy link
Contributor

batpigandme commented Apr 9, 2019

From the rename() docs

Use named arguments, e.g. new_name = old_name, to rename selected variables.
To turn the named character vector into named arguments, you have to use the splice !!! (big bang) operator.

Hopefully we can make the error message more informative, though.

library(dplyr)
newnames <- c("Sepal.Length", "Petal.Length") %>% 
  setNames(c("Sepal_Length", "Petal_Length"))

iris %>% select(newnames) %>% names
#> [1] "Sepal_Length" "Petal_Length"

iris %>% rename(newnames) %>% names
#> All arguments must be named

iris %>% select(!!!newnames) %>% names
#> [1] "Sepal_Length" "Petal_Length"
iris %>% rename(!!!newnames) %>% names
#> [1] "Sepal_Length" "Sepal.Width"  "Petal_Length" "Petal.Width" 
#> [5] "Species"

vars <- list(
  Sepal_Length = sym("Sepal.Length"),
  Petal_Length = sym("Petal.Length")
)

rename(iris, !!!vars) %>% head()
#>   Sepal_Length Sepal.Width Petal_Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa

Created on 2019-04-09 by the reprex package (v0.2.1)

EDIT For completeness, it also works without sym() with the !! operator:

library(dplyr)
vars <- c(Sepal_Length = "Sepal.Length", Petal_Length ="Petal.Length")
iris %>% select(!!vars) %>% names
#> [1] "Sepal_Length" "Petal_Length"
iris %>% rename(!!vars) %>% names
#> [1] "Sepal_Length" "Sepal.Width"  "Petal_Length" "Petal.Width" 
#> [5] "Species"

Created on 2019-04-09 by the reprex package (v0.2.1)

@jmobrien
Copy link
Author

jmobrien commented Apr 9, 2019

Thanks--though the text you copied is not actually in the help docs? This line is not followed by what you copied:

Use named arguments, e.g. new_name = old_name, to rename selected variables.

Am I missing something?

Also, it's more the inconsistency that troubles me--why does it work with select, then? The two do share a help page, after all, and I thought they largely shared functionality.

@batpigandme
Copy link
Contributor

ping @lionel- , is this a tidyselect issue?

@lionel-
Copy link
Member

lionel- commented Apr 9, 2019

Yes most likely.

@lionel- lionel- transferred this issue from tidyverse/dplyr Apr 9, 2019
@lionel- lionel- added bug an unexpected problem or unintended behavior rename labels Sep 9, 2019
@lionel-
Copy link
Member

lionel- commented Sep 11, 2019

We're going to deprecate this pattern:

iris %>% select(newnames)

The correct way to do it will be one of these (first one is recommended):

iris %>% select(one_of(newnames))
iris %>% select(!!newnames)

The reason is that if the data frame contains a newnames column, you'll get unwanted results. Conversely if you do select(x) because you expect a column named x, but there isn't one, and instead a variable x is picked up in the environment containing integers or names, you'll get surprising results.

For these reasons, we have decided to make a clear delimitation between expressions referring to columns and expressions referring to the context, like one_of(). As usual, unquoting with !! is another way of evaluating in the context unambiguously. Note that these considerations only apply to selections, not to actions (as in mutate(), summarise(), etc). See #76 for more about this.

The bottom line is that you need to unquote the character vector:

iris %>% rename(!!newnames)

@lionel- lionel- closed this as completed Sep 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug an unexpected problem or unintended behavior rename
Projects
None yet
Development

No branches or pull requests

3 participants