WedX - журнал о программировании и компьютерных науках

Можно ли просматривать .SD из браузера в [.data.table()?

При построении выражений для размещения в слоте j вызова [.data.table часто бывает полезно иметь возможность изучить и поэкспериментировать с содержимым .SD.

Эта наивная попытка не работает...

library(data.table)
DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9)

DT[, browser(), by=x]
# Called from: `[.data.table`(DT, , browser(), by = x)
Browse[1]> 
Browse[1]> .SD
# NULL data.table

... хотя переменная с именем .SD и несколько других, связанных с текущим подмножеством data.table, присутствуют в локальной среде

Browse[1]> ls(all.names = TRUE)
#  [1] ".BY"       ".GRP"      ".I"        ".iSD"      ".N"        ".SD"      
#  [7] "Cfastmean" "mean"      "print"     "x"        
Browse[1]> .N
# [1] 3
Browse[1]> .I
# [1] 4 5 6

Используя .I, я могу просмотреть что-то +/- вроде .SD, но было бы неплохо иметь прямой доступ к его значению:

Browse[1]> DT[.I]
#    x y v
# 1: b 1 4
# 2: b 3 5
# 3: b 6 6

Мои вопросы: Почему ожидаемое значение .SD недоступно напрямую из вызова browser() (в то время как .I, .N, .GRP и .BY доступны)? Есть ли альтернативный способ получить доступ к значению .SD?

27.03.2013

  • Интересно, в то время, когда вызывается browser(), .SD на самом деле чем-нибудь заполнен? str(.SD) показывает Classes ‘data.table’ and 'data.frame': 0 obs. of 0 variables и т. д. 27.03.2013
  • @GavinSimpson - я думаю, вы, вероятно, что-то там поняли. Частичный ответ, который я только что добавил, кажется дополнительным доказательством в этом направлении. Мне также интересно, как-то связана отложенная оценка .SD. 28.03.2013

Ответы:


1

Обновлено с учетом комментариев Мэтью Доула:

Оказывается, .SD внутри является средой, в которой оцениваются все выражения j, включая те, которые вообще не ссылаются явно на .SD. Заполнение его всеми столбцами DT для каждого подмножества DT недешево с точки зрения времени, поэтому [.data.table() не будет этого делать, если в этом нет действительной необходимости.

Вместо этого, широко используя ленивую оценку аргументов R, он предварительно просматривает невычисленное j выражение и добавляет только к .SD столбцам, на которые в нем есть ссылки. Если упоминается сам .SD, он добавляет все столбцы DT.

Итак, чтобы просмотреть .SD, просто включите ссылку на него в j-выражение. Вот одно из многих выражений, которые будут работать:

library(data.table)
DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9)

## This works
DT[, if(nrow(.SD)) browser(), by=x]
# Called from: `[.data.table`(DT, , if (nrow(.SD)) browser(), by = x)
Browse[1]> .SD
#    y v
# 1: 1 1
# 2: 3 2
# 3: 6 3

И вот еще парочка:

DT[,{.SD; browser()}, by=x]
DT[,{browser(); .SD}, by=x]  ## Notice that order doesn't matter

Чтобы убедиться, что .SD просто загружает столбцы, необходимые для выражения j, запустите их по очереди (введя .SD при входе в среду браузера и Q, чтобы выйти из нее и вернуться к обычной командной строке):

DT[, {.N * y ; browser()}, by=x]
DT[, {v^2 ; browser()}, by=x]
DT[, {y*v ; browser()}, by=x]
27.03.2013
  • Раздел 2.1 data.table FAQ относится к очень медленному вниз, что может повлечь за собой использование .SD. 28.03.2013
  • Джош, не совсем. раздел 2.1 часто задаваемых вопросов рекомендует использовать .SD, но не с with = FALSE. ‹quote› Объект SD эффективно реализован внутри и более эффективен, чем передача аргумента в функцию. Пожалуйста, не делайте этого : DT[,.SD[,"sales",with=FALSE],by=grp] ‹/quote›. 28.03.2013
  • @Arun - Это просто рекомендация не использовать with=FALSE? Думаю, я должен признать, что никогда не понимал, о чем именно говорится в этом разделе, поэтому просто избегал .SD, когда мог. 28.03.2013
  • Да. with = FALSE в основном имитирует эквивалент data.frame. Например, если вам нужно получить доступ к 3-му столбцу, вы можете сделать: DT[, 3, with = FALSE]. Но без этого .SD определенно быстрее, особенно при работе со столбцами (или по столбцам). 28.03.2013
  • +1 Да точно. Само наличие символа .SD в j приводит к тому, что .SD заполняется всеми столбцами подмножества. В противном случае .SD заполняется только теми столбцами, которые нужны j. Внутри, на уровне C, .SD является статической средой, в которой оценивается j. Именно здесь происходит вся магия, независимо от того, используется ли .SD (как символ) j или нет. Это то, на что ссылается FAQ 3.1, пункт 1. И именно поэтому мы советуем не использовать .SD, если только j действительно не нужны все столбцы и все строки из него (например, DT[,lapply(.SD,sum),by=...]). 28.03.2013
  • @MatthewDowle - очень поучительный комментарий. Спасибо! (1) В продолжение того, что вы сказали, даже это сработает: DT[, {browser(); .SD}, by=x]. Отредактирую свой ответ, чтобы отразить это, когда у меня будет шанс. (2) Re: Комментарий Аруна, должны ли эти два устройства быть одинаково быстрыми: DT[,.N*.SD[,v], by=x]; DT[,.N*.SD[,"v",with=FALSE], by=x]? Оптимизирует ли [.data.table первое выражение j, но не второе? Или, поскольку они оба ссылаются на .SD, получают ли они один и тот же удар? (3) Еще раз спасибо за всю вашу работу над этим проектом! 28.03.2013
  • (1) Да, порядок не имеет значения. Все выражение j сначала проверяется один раз, прежде чем начнется группировка. (2) Оба одинаково медленные и одинаково плохие методы (см. конец FAQ 2.1), потому что оба используют .SD расточительно, а также оба j вызывают [.data.table, которые имеют накладные расходы при зацикливании или группировании. Но дайте мне знать, если тесты докажут, что я ошибаюсь! (3) Нет проблем, спасибо! 28.03.2013
  • И все это благодаря ленивой оценке аргументов в R. Это одна из причин, почему data.table есть в R, а не, например, в Python или Julia. Без ленивой оценки R было бы невозможно проверить i и j и оптимизировать их перед оценкой, iiuc. 28.03.2013
  • @MatthewDowle Спасибо за проницательные комментарии здесь. Все очень интересно. 28.03.2013
  • @MattDowle Теперь, когда data.table реализуется в Python, мне любопытно ваше заявление о том, что data.table полагается на уникальную структуру ленивой оценки R. Что изменилось, что позволило реализовать data.table в Python? Или это не полная реализация? 07.10.2019
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]