Когда использовать функцию "с" и почему она хороша?

В чем преимущества использования with()? В файле справки упоминается, что он оценивает выражение в среде, которую он создает из данных. В чем преимущества этого? Быстрее ли создавать среду и оценивать ее там, а не просто оценивать ее в глобальной среде? Или есть что-то еще, что мне не хватает?

Ответ 1

with - это оболочка для функций без аргумента data

Есть много функций, которые работают с фреймами данных и принимают аргумент data, так что вам не нужно повторно вводить имя фрейма данных при каждой ссылке на столбец. lm, plot.formula, subset, transform - это всего лишь несколько примеров.

with - это обертка общего назначения, позволяющая использовать любую функцию, как если бы она имела аргумент данных.

Используя набор данных mtcars, мы могли бы подогнать модель с использованием аргумента данных или без него:

# this is obviously annoying
mod = lm(mtcars$mpg ~ mtcars$cyl + mtcars$disp + mtcars$wt)

# this is nicer
mod = lm(mpg ~ cyl + disp + wt, data = mtcars)

Однако, если (по какой-то странной причине) мы хотели найти mean в cyl + disp + wt, возникает проблема, поскольку у mean нет аргумента данных, как у lm. Это проблема, которую with решает:

# without with(), we would be stuck here:
z = mean(mtcars$cyl + mtcars$disp + mtcars$wt)

# using with(), we can clean this up:
z = with(mtcars, mean(cyl + disp + wt))

Обтекание foo() в with(data, foo(...)) позволяет нам использовать любую функцию foo, как если бы она имела аргумент data - то есть мы можем использовать имена столбцов без кавычек, предотвращая повторяющиеся data_name$column_name или data_name[, "column_name"].

Когда использовать with

Используйте with всякий раз, когда вам нравится интерактивно (консоль R) и в сценариях R, чтобы сохранить ввод текста и сделать ваш код более понятным. Чем чаще вам потребуется повторно вводить имя фрейма данных для одной команды (и чем длиннее имя фрейма данных!), Тем больше выгода от использования with.

Также обратите внимание, что with не ограничивается фреймами данных. От ?with:

Для метода по умолчанию with это может быть среда, список, фрейм данных или целое число, как в sys.call.

Я не часто работаю со средой, но когда я это делаю, я нахожу with очень удобным.

Когда вам нужны кусочки результата только для одной строки

Как говорит @Rich Scriven в комментариях, with может быть очень полезным, когда вам нужно использовать результаты чего-то вроде rle. Если вам нужны результаты только один раз, то его пример with(rle(data), lengths[values > 1]) позволяет использовать результаты rle(data) анонимно.

Когда следует избегать with

Когда есть аргумент data

Многие функции, имеющие аргумент data, используют его для более простого синтаксиса при вызове. Большинство функций моделирования (например, lm) и многие другие (ggplot!) Многое делают с предоставленным data. Если вы используете with вместо аргумента data, вы ограничите доступные вам функции. Если есть аргумент data, используйте аргумент data, а не with.

Добавление в среду

В моем примере выше результат был присвоен глобальной среде (bar = with(...)). Чтобы сделать назначение внутри списка/среды/данных, вы можете использовать within. (В случае data.frames, transform также хорош.)

В пакетах

Не используйте with в пакетах R. В help(subset) есть предупреждение, которое также может относиться и к with:

Предупреждение Это удобная функция, предназначенная для интерактивного использования. Для программирования лучше использовать стандартные функции поднабора, такие как [, и, в частности, нестандартная оценка подмножества аргументов может иметь непредвиденные последствия.

Если вы создаете пакет R с помощью with, при его проверке вы, вероятно, получите предупреждения или заметки об использовании переменных без видимой привязки. Это сделает пакет неприемлемым для CRAN.

Альтернативы with

Не используйте attach

Многие (в основном датированные) учебники R используют attach, чтобы избежать повторного ввода имен фреймов данных, делая столбцы доступными для глобальной среды. attach широко считается плохой практикой, и ее следует избегать. Одна из основных опасностей присоединения заключается в том, что столбцы данных могут стать не синхронизированными, если они будут изменены индивидуально. with избегает этой ловушки, потому что она вызывается по одному выражению за раз. В Qaru есть много вопросов, когда новые пользователи следуют старому учебнику и сталкиваются с проблемами из-за attach. Простое решение всегда не использовать attach.

Использование with все время кажется слишком повторяющимся

Если вы делаете много шагов манипулирования данными, вы можете обнаружить, что начинаете каждую строку кода с with(my_data, .... Вы можете подумать, что это повторение почти так же плохо, как и не использование with. Оба пакета data.table и dplyr предлагают эффективную обработку данных с неповторяющимся синтаксисом. Я бы посоветовал вам научиться использовать один из них. Оба имеют отличную документацию.

Ответ 2

Я использую его, когда не хочу набирать dataframe$. Например

with(mtcars, plot(wt, qsec))

а не

plot(mtcars$wt, mtcars$qsec)

Первая просматривает wt и qsec в mtcars data.frame. Конечно,

plot(qsec~wt, mtcars)

более подходит для сюжетных или других функций, которые принимают аргумент data=.