What does the dplyr period character "." reference?

11,886

Solution 1

The dot is used within dplyr mainly (not exclusively) in mutate_each, summarise_each and do. In the first two (and their SE counterparts) it refers to all the columns to which the functions in funs are applied. In do it refers to the (potentially grouped) data.frame so you can reference single columns by using .$xyz to reference a column named "xyz".

The reasons you cannot run

filter(df, . == 5)

is because a) filter is not designed to work with multiple columns like mutate_each for example and b) you would need to use the pipe operator %>% (originally from magrittr).

However, you could use it with a function like rowSums inside filter when combined with the pipe operator %>%:

> filter(mtcars, rowSums(. > 5) > 4)
Error: Objekt '.' not found

> mtcars %>% filter(rowSums(. > 5) > 4) %>% head()
    lm cyl disp  hp drat    wt  qsec vs am gear carb
1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
3 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
4 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
5 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
6 14.3   8  360 245 3.21 3.570 15.84  0  0    3    4

You should also take a look at the magrittr help files:

library(magrittr)
help("%>%")

From the help page:

Placing lhs elsewhere in rhs call Often you will want lhs to the rhs call at another position than the first. For this purpose you can use the dot (.) as placeholder. For example, y %>% f(x, .) is equivalent to f(x, y) and z %>% f(x, y, arg = .) is equivalent to f(x, y, arg = z).

Using the dot for secondary purposes Often, some attribute or property of lhs is desired in the rhs call in addition to the value of lhs itself, e.g. the number of rows or columns. It is perfectly valid to use the dot placeholder several times in the rhs call, but by design the behavior is slightly different when using it inside nested function calls. In particular, if the placeholder is only used in a nested function call, lhs will also be placed as the first argument! The reason for this is that in most use-cases this produces the most readable code. For example, iris %>% subset(1:nrow(.) %% 2 == 0) is equivalent to iris %>% subset(., 1:nrow(.) %% 2 == 0) but slightly more compact. It is possible to overrule this behavior by enclosing the rhs in braces. For example, 1:10 %>% {c(min(.), max(.))} is equivalent to c(min(1:10), max(1:10)).

Solution 2

The dot has a special meaning within funs. In that context it refers to the dummy parameter. See ?funs for a descrption.

funs constructs a "fun_list" class object which represents a list of functions. Each argument of funs is a function name, character string representing a function name or an expression representing the body of the function. In the last case, within the expression representing the function body, the argument of the function is represented by dot so that . == 5 refers to the function function(.) . == 5 (although dplyr does not actually construct that function but rather uses a "fun_list" object instead).

In this example, mutate_each will run the function once for each column so that this does the same thing as in the question except it also prints out the input each time the constructed function (it is not actually constructed but we can think about it that way) is called:

> out <- mutate_each(df, funs({print(.); . == 5}))
[1] 1 2 3 4 5
[1] 1 2 3 4 5
[1] 1 2 3 4 5
[1] 1 2 3 4 5
[1] 1 2 3 4 5

In your filter example, funs is not being used and filter does not work with "fun_list" objects anyways.

dot has other meanings within other contexts within dplyr and can have other meanings within other contexts for other packages as well.

Share:
11,886
Megatron
Author by

Megatron

BY DAY: Mining energon, battling Autobots, planning triumphant return to Cybertron. FOR FUN: r analyses of any publicly available data, python for ML, git for all of the above "If something cannot go on forever, it will stop." - Herbert Stein's Law "The perfect is the enemy of the good." "A camel is a horse designed by committee." "All models are wrong, but some are useful." - George Box "There are three kinds of lies: lies, damned lies and statistics." "If you torture the data long enough, it will confess to anything." "The enemy of art is the absence of limitations." - Orson Welles "If you're explaining, you're losing." "Excessive civility without adequate candor means that everyone feels good but not much is really being discussed. Candor is more proactive." - Todd Dewett "Five minutes of extra care saves an hour" "I have not failed. I've just found 10,000 ways that won't work." - Thomas Edison

Updated on June 03, 2022

Comments

  • Megatron
    Megatron about 2 years

    What does the period . reference in the following dplyr code?:

    (df <- as.data.frame(matrix(rep(1:5, 5), ncol=5)))
    #    V1 V2 V3 V4 V5
    #  1  1  1  1  1  1
    #  2  2  2  2  2  2
    #  3  3  3  3  3  3
    #  4  4  4  4  4  4
    #  5  5  5  5  5  5
    
    dplyr::mutate_each(df, funs(. == 5))
    #       V1    V2    V3    V4    V5
    #  1 FALSE FALSE FALSE FALSE FALSE
    #  2 FALSE FALSE FALSE FALSE FALSE
    #  3 FALSE FALSE FALSE FALSE FALSE
    #  4 FALSE FALSE FALSE FALSE FALSE
    #  5  TRUE  TRUE  TRUE  TRUE  TRUE
    

    Is this shorthand for "all columns"? Is this . specific dplyr syntax or is it general R syntax (as discussed here)?

    Also, why does the following code result in an error?

    dplyr::filter(df, . == 5)
    #  Error: object '.' not found