ewaluacja i wycena w danych.tabela

Co mi umyka?

d = data.table(a = 1:5)

d[, a]                   # 1 2 3 4 5
d[, sum(a)]              # 15

d[, eval(quote(a))]      # 1 2 3 4 5
d[, sum(eval(quote(a)))] # 15

quoted_a = quote(a)
d[, eval(quoted_a)]      # 1 2 3 4 5
d[, sum(eval(quoted_a))] # Error in eval(expr, envir, enclos) : object 'a' not found
Co się dzieje? Biegam R 2.15.0 i data.table 1.8.9.
Author: eddi, 2013-04-10

1 answers

UPDATE (eddi): od Wersja 1.8.11 to zostało naprawione i {[2] } nie jest potrzebne w przypadkach, w których wyrażenie może być obliczone w miejscu, jak w OP. ponieważ obecnie OBECNOŚĆ .SD wyzwala budowę pełnego .SD, spowoduje to znacznie szybsze prędkości w niektórych przypadkach.


Chodzi o to, że wywołania do eval() są traktowane inaczej niż można sobie wyobrazić w kodzie implementującym [.data.table(). W szczególności [.data.table() zawiera specjalną ocenę gałęzie dla i i j wyrażeń zaczynających się od symbolu eval. Kiedy zawijasz połączenie do eval wewnątrz połączenia do sum(), eval nie jest już pierwszym elementem parsowanego / podstawionego wyrażenia, a specjalna gałąź oceny jest pomijana.

Oto bit kodu w funkcji potwora wyświetlany przez wpisanie getAnywhere("[.data.table"), który zapewnia specjalne ograniczenie dla wywołań do eval() przekazywanych przez [.data.table() ' s j-argument:

jsub = substitute(j)
    ...
    # Skipping some lines
    ...
jsubl = as.list.default(jsub)
if (identical(jsubl[[1L]], quote(eval))) {  # The test for eval 'on the outside' 
    jsub = eval(jsubl[[2L]], parent.frame(), parent.frame())
    if (is.expression(jsub)) 
        jsub = jsub[[1L]]
}

Jako obejście, albo podążaj za przykładem w danych.table FAQ 1.6 (PDF here ), lub wprost skierować eval() w stronę .SD, zmiennej lokalnej, która przechowuje kolumny dowolnych danych.tabela, na której operujesz (tutaj d). (Aby dowiedzieć się więcej o roli .SD, Zobacz kilka pierwszych akapitów tej odpowiedzi).

d[, sum(eval(quoted_a, envir=.SD))]
 20
Author: Josh O'Brien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:46