Skip to content

Is it true that as.data.table() does a shallow copy? #3665

Description

@hadley

It seems that as.data.table(dt) creates a "shallow" copy of its input? The reprex below suggests it does, but is this something that I can rely on?

library(data.table)

# Does it copy?
dt <- data.table(x = 1:3)
dt2 <- as.data.table(dt)
dt[, y := x + 1]
dt
#>    x y
#> 1: 1 2
#> 2: 2 3
#> 3: 3 4
dt2
#>    x
#> 1: 1
#> 2: 2
#> 3: 3


# Is it fast than copy?
mtcars_big <- data.table(mtcars[rep(1:32, each = 1e5), ])

bench::mark(
  copy(mtcars_big),
  as.data.table(mtcars_big),
  check = FALSE
)[1:6]
#> Warning: Some expressions had a GC in every iteration; so filtering is
#> disabled.
#> # A tibble: 2 x 6
#>   expression                     min     mean   median      max `itr/sec`
#>   <chr>                     <bch:tm> <bch:tm> <bch:tm> <bch:tm>     <dbl>
#> 1 copy(mtcars_big)           274.9ms    283ms    283ms    291ms      3.53
#> 2 as.data.table(mtcars_big)   85.3ms    129ms    123ms    183ms      7.77

Created on 2019-06-26 by the reprex package (v0.2.1.9000)

Activity

  1. hadley commented on Jun 26, 2019

    @hadley
    ContributorAuthor

    Ok, it's probably not doing a shallow copy, since both functions get much slower for a larger table:

    library(data.table)
    
    mtcars_big <- data.table(mtcars)[rep(1:32, each = 1e6), ]
    
    bench::mark(
      copy(mtcars_big),
      as.data.table(mtcars_big),
      check = FALSE
    )[1:6]
    #> Warning: Some expressions had a GC in every iteration; so filtering is
    #> disabled.
    #> # A tibble: 2 x 6
    #>   expression                     min     mean   median      max `itr/sec`
    #>   <chr>                     <bch:tm> <bch:tm> <bch:tm> <bch:tm>     <dbl>
    #> 1 copy(mtcars_big)             2.75s    2.75s    2.75s    2.75s     0.363
    #> 2 as.data.table(mtcars_big)    2.39s    2.39s    2.39s    2.39s     0.418

    Created on 2019-06-26 by the reprex package (v0.2.1.9000)

  2. hadley commented on Jun 26, 2019

    @hadley
    ContributorAuthor

    But maybe dt[TRUE, ] does?

    library(data.table)
    
    dt <- data.table(x = 1:3)
    dt2 <- dt[TRUE, ]
    
    dt[, y := 1]
    dt
    #>    x y
    #> 1: 1 1
    #> 2: 2 1
    #> 3: 3 1
    dt2
    #>    x
    #> 1: 1
    #> 2: 2
    #> 3: 3
    
    mtcars_big <- data.table(mtcars)[rep(1:32, each = 1e6), ]
    
    bench::mark(
      copy(mtcars_big),
      mtcars_big[TRUE, ],
      check = FALSE
    )[1:6]
    #> Warning: Some expressions had a GC in every iteration; so filtering is
    #> disabled.
    #> # A tibble: 2 x 6
    #>   expression              min     mean   median      max `itr/sec`
    #>   <chr>              <bch:tm> <bch:tm> <bch:tm> <bch:tm>     <dbl>
    #> 1 copy(mtcars_big)       2.7s     2.7s     2.7s     2.7s     0.370
    #> 2 mtcars_big[TRUE, ]   80.3µs    304µs  109.1µs  291.2ms  3290.

    Created on 2019-06-26 by the reprex package (v0.2.1.9000)

  3. franknarf1 commented on Jun 26, 2019

    @franknarf1
    Contributor

    Regarding DT[TRUE] I think that is just a temporary option for shallow copy until shallow() is exported: #3214 (comment)

    For the other operation you're doing (as.data.table on a data.table), the internals are written in R so there's no need to treat it as a black box:

    > data.table:::as.data.table.data.table
    function (x, ...) 
    {
        x = copy(x)
        setattr(x, "class", .resetclass(x, "data.table"))
        return(x)
    }
    <bytecode: 0x0000000010af4280>
    <environment: namespace:data.table>
    

    I usually use data.table::address to check if a copy is made (and, I guess there are analogues in pryr or base R).

  4. jangorecki commented on Jun 26, 2019

    @jangorecki
    Member

    The latter one does, see #3214

  5. hadley commented on Jun 26, 2019

    @hadley
    ContributorAuthor

    I guess I'm asking if DT[TRUE] will continue to perform a shallow copy in the future, or it's seen as an undocumented feature that I shouldn't rely on. #3214 (comment) suggests I shouldn't rely on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    by-referenceIssues related to by-reference/copying behavior

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions