[datatable-help] Wonder whether there is an easier way to changepart of data.table values

Branson Owen branson.owen at gmail.com
Fri Jul 30 01:38:16 CEST 2010


Dear Tom,

> [<-.data.table and $<-.data.table both need a bit of work.
>> DT <- data.table(A = c("A", "Z"), Z = 1:10, key = "A")
> You've found the DT$column[index] = new value approach, but if you use that on keys, DT may no longer be sorted right:
>> DT$A[10] <- "A"
>> DT
>      A   Z
>  [1,] A   1
>  [2,] A   3
>  [3,] A   5
>  [4,] A   7
>  [5,] A   9
>  [6,] Z   2
>  [7,] Z   4
>  [8,] Z   6
>  [9,] Z   8
> [10,] A 100


Yeah, I noticed it. I can even "re-assign" non-integer value to key
column and it won't complain. It checks validity only when
constructing.


> Since we now inherit from data.frames, we can just use [<-.data.frame. It still has the problem that it won't remove the key if the key'd column changes.
>> `[<-.data.table` <- `[<-.data.frame`
>> DT[9,"Z"] <- 22
>> DT
>      A   Z
>  [1,] A   1
>  [2,] A   3
>  [3,] A   5
>  [4,] A   7
>  [5,] A   9
>  [6,] Z   2
>  [7,] Z   4
>  [8,] Z   6
>  [9,] Z  22
> [10,] A 100



> I'm not sure we want to be able to do DT[select,] <- something.


I think that would ok since we still have some way to achieve it.


> Something like the following will work for a simple select:
>> DT <- data.table(A = c("A", "Z"), Z = 1:10, key = "A")
>> `[<-.data.table` <- `[<-.data.frame`


This is something I dare not do if you don't provide a hint.


>> DT[DT[J("A"), which=TRUE, mult="all"], "Z"] <- 44
>> DT
>      A  Z
>  [1,] A 44
>  [2,] A 44
>  [3,] A 44
>  [4,] A 44
>  [5,] A 44
>  [6,] Z  2
>  [7,] Z  4
>  [8,] Z  6
>  [9,] Z  8
> [10,] Z 10
>
> The following is equivalent:
>> DT$Z[DT[J("A"), which=TRUE, mult="all"]] <- 55
>> DT
>      A  Z
>  [1,] A 55
>  [2,] A 55
>  [3,] A 55
>  [4,] A 55
>  [5,] A 55
>  [6,] Z  2
>  [7,] Z  4
>  [8,] Z  6
>  [9,] Z  8
> [10,] Z 10

> I'd prefer to use as much of [<-.data.frame and $<-.data.frame as possible.  $<-.data.frame is pretty easy:
>> "$<-.data.table" = function (x, name, value) {
> +     res <- `$<-.data.frame`(x, name, value)
> +     if (any(name %in% key(x)))
> +         key(res) <- NULL
> +     res
> + }
>> DT <- data.table(A = c("A", "Z"), Z = 1:10, key = "A")
>> DT$Z[3] <- 33
>> key(DT)
> [1] "A"
>> DT$A[10] <- "A"
>> key(DT)
> NULL
>> DT
>      A  Z
>  [1,] A  1
>  [2,] A  3
>  [3,] A 33
>  [4,] A  7
>  [5,] A  9
>  [6,] Z  2
>  [7,] Z  4
>  [8,] Z  6
>  [9,] Z  8
> [10,] A 10
> This doesn't allow x to be a data.table-style select. If we want that, I could experiment some.
> [<-.data.table is more challenging, but I could take a shot on a plane ride next week.

Wow, thanks a lot. I hope I can buy you more plane rides for more easy
and cool features. ;-)

Sincerely appreciate your detailed answers!

Best regards,


More information about the datatable-help mailing list