Почему data.table определен: = вместо перегрузки <-? - PullRequest
43 голосов
/ 12 августа 2011

data.table ввел оператор: =. Почему бы не перегрузить <-? </p>

Ответы [ 2 ]

28 голосов
/ 12 августа 2011

Есть два места, которые <- могут быть «перегружены»:

x[i, j] <- value           # 1
x[i, {colname <- value}]   # 2

Первый копирует все x в *tmp*, изменяет эту рабочую копию и присваивает обратно x. Это тема R (src / main / eval.c и subassign.c), недавно обсуждаемая на r-devel здесь . Похоже, можно изменить R, чтобы разрешить пакетам, или самому R, чтобы избежать этой копии до *tmp*, но в настоящее время это невозможно, IIUC.

Второй, на мой взгляд, относится к ответу Оуэна. Если вы согласны с тем, что это нормально делать присвоение по ссылке в j, то какой оператор? Согласно комментарию к ответу Оуэна, <- и <<- уже используются пользователями в j, поэтому мы натолкнулись на :=.

Даже если [<- не скопировал весь x, нам все равно нравится := в j, поэтому мы можем делать такие вещи:

DT[,{newcol1:=sum(a)
     newcol2:=a/newcol1}, by=group]

Если новые столбцы добавляются в виде ссылки на таблицу, а RHS каждого := оценивается в каждой группе. (Когда: = внутри группы реализовано.)


Обновление октябрь 2012

По состоянию на 1.8.2 (в CRAN в июле 2012 г.) := по группе было реализовано для добавления или обновления отдельных столбцов; то есть, одна LHS :=. И теперь в v1.8.3 (в R-Forge на момент написания) можно добавить несколько столбцов по группам; например.,

DT[, c("newcol1","newcol2") := .(sum(a),sum(b)), by=group]

или, возможно, более элегантно:

DT[,`:=`(newcol1=sum(a),
         newcol2=sum(b)), by=group]

Но пока еще не реализовано итеративное многократное RHS , где второе выражение может использовать результат первого, пока не реализовано ( FR # 1492 ). Таким образом, это все равно выдаст ошибку "newcol1 not found", и ее необходимо выполнить в два этапа:

DT[,`:=`(newcol1=sum(a),
         newcol2=a/newcol1), by=group]
16 голосов
/ 12 августа 2011

Я не думаю, что есть какая-либо техническая причина, в которой это должно быть необходимо, по следующей причине: := используется только внутри [...], поэтому всегда указывается в кавычках.[...] просматривает дерево выражений, чтобы увидеть, есть ли в нем :=.

Это означает, что он на самом деле не действует как оператор и не перегружен;поэтому они могли выбрать практически любого оператора, которого хотели.Я думаю, может быть, это выглядело лучше?Или менее запутанным, потому что это явно не <-?

(Обратите внимание, что если бы := использовалось вне из [...], это не могло бы быть <-, потому что вы не можетефактически перегрузка <-. <- Не оценивает свой левый аргумент, поэтому не знает, что это за тип).

...