Почему не рекомендуется использовать attach() в R, и что я должен использовать вместо этого?
Предположим, что у нас есть кадр данных x
, который содержит столбцы job
и income
. Для данных в кадре обычно требуются команды x$job
для данных в столбце job
и x$income
для данных в столбце income
.
Однако, используя команду attach(x)
, можно отказаться от имени фрейма данных и символа $
при обращении к тем же данным. Следовательно, x$job
становится job
, а x$income
становится income
в R-коде.
Проблема заключается в том, что многие эксперты из R советуют НЕ использовать команду attach()
при кодировании в R.
В чем главная причина этого? Что следует использовать вместо этого?
Ответы
Ответ 1
Когда его использовать:
Я использую attach()
, когда хочу, чтобы среда, в которой вы попадаете в большинстве пакетов статистики (например, Stata, SPSS), работает с одним прямоугольным набором данных за раз.
Когда не использовать его:
Однако он становится очень грязным, и код быстро становится нечитаемым, когда у вас есть несколько разных наборов данных, особенно если вы фактически используете R как грубую реляционную базу данных, где разные прямоугольники данных, все относящиеся к проблеме под рукой и, возможно, используемые разными способами для сопоставления данных из разных прямоугольников, имеют переменные с тем же именем.
Функция with()
или аргумент data=
для многих функций являются отличными альтернативами для многих случаев, когда attach()
является соблазнительной.
Ответ 2
Другая причина не использовать attach
: он позволяет получить доступ к значениям столбцов кадра данных для чтения (доступа) и как они были при прикреплении. Это не сокращение текущего значения этого столбца. Два примера:
> head(cars)
speed dist
1 4 2
2 4 10
3 7 4
4 7 22
5 8 16
6 9 10
> attach(cars)
> # convert stopping distance to meters
> dist <- 0.3048 * dist
> # convert speed to meters per second
> speed <- 0.44707 * speed
> # compute a meaningless time
> time <- dist / speed
> # check our work
> head(cars)
speed dist
1 4 2
2 4 10
3 7 4
4 7 22
5 8 16
6 9 10
Никаких изменений в наборе данных cars
не было, даже если dist
и speed
были назначены.
Если явно назначено обратно в набор данных...
> head(cars)
speed dist
1 4 2
2 4 10
3 7 4
4 7 22
5 8 16
6 9 10
> attach(cars)
> # convert stopping distance to meters
> cars$dist <- 0.3048 * dist
> # convert speed to meters per second
> cars$speed <- 0.44707 * speed
> # compute a meaningless time
> cars$time <- dist / speed
> # compute meaningless time being explicit about using values in cars
> cars$time2 <- cars$dist / cars$speed
> # check our work
> head(cars)
speed dist time time2
1 1.78828 0.6096 0.5000000 0.3408862
2 1.78828 3.0480 2.5000000 1.7044311
3 3.12949 1.2192 0.5714286 0.3895842
4 3.12949 6.7056 3.1428571 2.1427133
5 3.57656 4.8768 2.0000000 1.3635449
6 4.02363 3.0480 1.1111111 0.7575249
dist
и speed
, на которые ссылаются вычисления time
, являются исходными (нетрансформированными) значениями; значения cars$dist
и cars$speed
, когда cars
был прикреплен.
Ответ 3
Я думаю, что нет ничего плохого в использовании attach
. Я сам его не использую (опять же, я люблю животных, но не оставляю их). Когда я думаю о attach
, я думаю, что надолго. Конечно, когда я работаю с script, я знаю его внутри и снаружи. Но через неделю, месяц или год, когда я вернусь к script, я нахожу накладные расходы при поиске, где определенная переменная, слишком дорого. Множество методов имеет аргумент data
, который делает вызывающие переменные довольно легкими (sensu lm(x ~ y + z, data = mydata)
). Если нет, я считаю использование with
к моему удовлетворению.
Вкратце, в моей книге приложение прекрасно подходит для короткого быстрого поиска данных, но для разработки сценариев, которые я или другие могут использовать, я стараюсь, чтобы мой код был как можно читабельным (и переносимым), насколько это возможно.
Ответ 4
Если вы выполняете attach(data)
несколько раз, например, 5 раз, то вы можете увидеть (с помощью search()
), что ваши данные были прикреплены 5 раз в рабочей области. Поэтому, если вы один раз отсоедините (detach(data)
), в среде все еще будет data
4 раза. Следовательно, with()/within()
- лучшие варианты. Они помогают создать локальную среду, содержащую этот объект, и вы можете использовать ее без каких-либо путаниц.