Play with the tribe of attributes

2019-11-23

Verbs for easy manipulation of attributes

The tribe package provides verbs for easy manipulation of attributes. These verbs are:

The function tribe is a convenient synonym of attributes, with the slight difference that it always returns a named list.

df <- data.frame(x = 1:2, y = 2:3) %>%
  at_mutate(example="yes", package="dplyr")
tribe(df)
#> List of 5
#>  $ names    : chr [1:2] "x" "y"
#>  $ row.names: int [1:2] 1 2
#>  $ class    : chr "data.frame"
#>  $ example  : chr "yes"
#>  $ package  : chr "dplyr"

Use at_slice to extract attribute values:

at_slice(df, names)
#> [1] "x" "y"

Each verb has its standard evaluation version; for instance at_slice_ is the standard evaluation version of at_slice:

at_slice_(df, "class")
#> [1] "data.frame"
at_slice_(df, ~ package)
#> [1] "dplyr"

Similarly at_mutate_ is the standard evaluation version of at_mutate:

df <- df %>%
  at_mutate_(package = ~ NULL, # deletes the attribute called 'package'
             example = ~ "no")
tribe(df)
#> List of 4
#>  $ names    : chr [1:2] "x" "y"
#>  $ row.names: int [1:2] 1 2
#>  $ class    : chr "data.frame"
#>  $ example  : chr "no"

A new pipe that preserves attributes

The tribe package builds on the magrittr package and brings a new pipe %@>% similar to the pipe %>% that enables propagation of attributes.

df <- data.frame(x = 1:2, y = 2:3) %>%
 at_mutate(example="yes",
           package="tribe", 
           class = c("my_tbl", "data.frame"))

Attributes just created are often lost when the object passes through dplyr verbs, for instance:

tribe(df %>% mutate(z=3))
#> List of 3
#>  $ names    : chr [1:3] "x" "y" "z"
#>  $ class    : chr "data.frame"
#>  $ row.names: int [1:2] 1 2

With the new pipe %@>%, most attributes propagate:

tribe(df %@>% mutate(z=3))
#> List of 5
#>  $ names    : chr [1:3] "x" "y" "z"
#>  $ row.names: int [1:2] 1 2
#>  $ class    : chr [1:2] "my_tbl" "data.frame"
#>  $ example  : chr "yes"
#>  $ package  : chr "tribe"

Behind the scene, the shield function operates:

# Attributes are lost when the object passes through dplyr verbs
df2 <- df %>% mutate(z = 3)
tribe(df2)
#> List of 3
#>  $ names    : chr [1:3] "x" "y" "z"
#>  $ class    : chr "data.frame"
#>  $ row.names: int [1:2] 1 2

# Most attributes are kept
df3 <- shield(df2, tribe(df), propagate = "most")
tribe(df3)
#> List of 5
#>  $ names    : chr [1:3] "x" "y" "z"
#>  $ row.names: int [1:2] 1 2
#>  $ class    : chr "data.frame"
#>  $ example  : chr "yes"
#>  $ package  : chr "tribe"

# To keep the class, use 'keep_also'
df4 <- shield(df2, tribe(df), propagate = "most", keep_also = "class")
tribe(df4)
#> List of 5
#>  $ names    : chr [1:3] "x" "y" "z"
#>  $ row.names: int [1:2] 1 2
#>  $ class    : chr [1:2] "my_tbl" "data.frame"
#>  $ example  : chr "yes"
#>  $ package  : chr "tribe"

One can create a new pipe to adjust attributes propagation settings:

"%newpipe>%" <- make_pipe(propagate="none", keep_also = "example")
tribe(df %newpipe>% mutate(z=3))
#> List of 1
#>  $ example: chr "yes"