'detach() 사용 시 주의할 점'에 해당되는 글 1건

  1. 2015.07.17 R attach(), detach() 함수 사용 시 주의할 점
 

지난번 포스팅에서 데이터 프레임을 편리하게 사용할 때 사용할 수 있는 attach(), detach() 를 살펴보았습니다.

 

이번에는 주의할 점을 알아보도록 하겠습니다.  attach(), detach()가 편리한 기능이기는 합니다만, 아래의 3가지 경우 처럼 주의해서 사용하지 않으면 R 초보자의 경우 에러가 왜, 어디서 나는지 몰라서 애를 먹고, 심한 경우 R에 대해 '배우기 어려운 언어'라는 인식을 가지게 할 수 있는 함정이 바로 오늘 포스팅하는 내용이 되겠습니다. 

 

R 프로그래밍 하시는 분들, attach(), detach() 자주 쓰시는 분들은 반드시 숙지하시고 실수 하지 않기 위해, 혹은 실수 했더라도 콘솔에 나온 오류 메시지를 읽고서 뭐를 잘못했고 어떻게 대처해야 하는지를 알기 위해서 금번 포스팅을 읽어보시면 도움일 될거라 믿습니다.



 attach(), detach() 사용 시 주의할 점


(1) attach()후에 작업 공간 내 같은 이름, 다른 길이의 객체가 있으면 충돌(중복)
: 다음에 오류xy.coords(x, y, xlabel, ylabel, log) : 'x' and 'y' lengths differ

 

R에 내장되어 있는 'mtcars' 데이터 프레임을 가져다가 실습을 해보면서 설명드리겠습니다.

> ## attach(), detach() 사용할 때 주의할 점
> 
> str(mtcars) # mtcars 데이터 구조 확인
'data.frame':	32 obs. of  11 variables:
 $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
 $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
 $ disp: num  160 160 108 258 360 ...
 $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
 $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
 $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
 $ qsec: num  16.5 17 18.6 19.4 17 ...
 $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
 $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
 $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
 $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
> head(mtcars) # 상위 6개 관측치 미리보기
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

 

 

attach()로 특정 데이터 프레임을 활성화 시킨 후에, 그 데이터 프레임에 있는 변수명과 같은 이름으로 벡터를 신규 생성하게 되면 R은 나중에 신규로 생성한 벡터 변수를 가져다가 작업을 하게 됩니다.  즉, 기존의 데이터 프레임의 변수가 새로운 수치로 변환이 되는게 아니라, 신규로 별도의 벡터가 따로 생기게 되다 보니 R이 동명이인을 두고 어찌할 바를 모르게 되는 겁니다. 이때 관측치 객수가 서로 다르다면 아래 예처럼 관측치 길이가 다르다고 에러 메시지가 뜨겠지요?

 

> attach(mtcars) # mtcars 데이터 프레임 활성화
> plot(hp, mpg) # 마력(hp: house power), 연비(mpg: mileage per gas) plot 그리기 OK
 

> # 마력, 연비 산포도 생성 성공

 

 
 
> 

> # mpg 라는 동일한 이름의 벡터를 생성 후 동일하게 산포도 명령 실행하면?
>
mpg <- c(20.0, 21.0, 19.2, 18.4, 19.9) # 동일한 이름의 mpg 벡터 신규 생성 > plot(mpg, hp) # 마력(hp), 연비(mpg) plot 그리기 에러발생 Error in xy.coords(x, y, xlabel, ylabel, log) : 'x' and 'y' lengths differ > > detach(mtcars)


서로 다른 의미(대상)의 벡터라면 이름을 다르게 해서 신규 생성하는게 답입니다. 그런데, R 프로그램 길게 짜다보면 인간인지라 실수로 중복 이름 벡터를 생성할수도 있고 하니, 간단한 명령어 실행할 때 에러를 원천 차단하려면,

 

(방법1)  '$'로 데이터 프레임을 지정(할당)해주고 변수를 불러오면 됩니다. 

 

> # 방법 1: '$' 로 데이터 프레임을 지정(할당)
> plot(mtcars$mpg, mtcars$hp)

 

 

 

 

 

 

(방법 2) detach() 후에, rm()으로 충돌(중복)되는 동일 이름 벡터 삭제 후 attach(), detach() 함수 활용

 

> # 방법 2: rm()으로 충돌(중복)되는 동일 이름 벡터 삭제 후 attach() 함수 활용

> detach(mtcars) # 활성화

> rm(mpg)  # 신규로 생성했었던 mpg 벡터 삭제

> attach(mtcars)

> plot(mpg, hp) # 다시 산점도 그리면 ok

 

 

 

 

 

> detach(mtcars)  # 활성화 해제

 

 

데이터 프레임을 attach()로 활성화 했다가 다 썼으면 끝에 꼭 detach()로 활성화 해제 잊지 말아야 겠죠.

 

 

(2) attach()후에 작업 공간 내 같은 이름, 다른 길이의 객체가 있으면 충돌(중복)
: The following object(s) are masked _by_ '.GlobalEnv' :

 

저는 R 초보일 때 분석하다 보면 이런 에러 메시지 많이 당했었고, 그때마다 이게 무슨 의미인지 몰라서 당황했었습니다. 아래 예제를 보면서 어떠할 때 이런 에러가 뜨는지 알아보겠습니다.

 

> # mtcars도 있는 동일한 이름의 hp 벡터 신규 생성 > hp <- c(120, 160, 110, 220)

 

# 우측 상단의 Global Environment 창에 hp 라는 벡터가 새로 생겼음을 확인할 수 있음

 

 

 

이런 상태에서 attach(mtcars)로 활성화(메모리에 임시로 데이터를 올리게 되면)를 하게 되면 mtcars 데이터 프레임에도 hp 라는 변수가 이미 들어있기 때문에 충돌이 나는 것입니다.

 

> attach(mtcars)
The following object is masked _by_ .GlobalEnv:

    hp

The following objects are masked from mtcars (pos = 3):

    am, carb, cyl, disp, drat, gear, hp, mpg, qsec, vs, wt
 
 
 

> hp # mtcars 데이터 프레임의 hp가 아니라 새로 생성한 벡터 hp가 호출됨 [1] 120 160 110 220

> > mtcars$hp # mtcars()$hp라고 해야지 mtcars 데이터 프레임 내 hp 벡터를 호출해옴 [1] 110 110 93 110 175 105 245 62 95 123 123 180 180 180 205 215 230 66 52 65 97 150 150 245 175 66 91 [28] 113 264 175 335 109

>

 

> rm(hp) # rm()으로 삭제한 이후에야 mtcars 데이터 프레임 내 hp를 호출하게 됨 > hp [1] 110 110 93 110 175 105 245 62 95 123 123 180 180 180 205 215 230 66 52 65 97 150 150 245 175 66 91 [28] 113 264 175 335 109


 이럴때는 rm()으로 중복되는 벡터를 삭제해주면 됩니다.

만약 생략해야 할 벡터가 많아서 일일이 rm() 명령어 치기가 귀찮다면 RStudio의 우측 상단에 붓 모양의 아이콘 클릭하면 전부 지워집니다. 전부 지워지니깐 조심해야 겠지만, 만약 전부 지워도 되는 거라면, 자꾸 에러가 나는데 뭐가 뭔지 잘 모르겠고 처음부터 다시 시작하고 싶다면 RStudio 우측 상단 붓 모양 아이콘으로 깔끔히 정리하고 R Script 짜놓은거 위에서 부터 순서대로 다시 해보면 실행 성공하는 경우 있습니다.

 

 

 

(3) attach()로 데이터 프레임을 메모리로 호출한 이후에 원본 데이터 프레임을 변경한 경우

 

attach()로 활성화 시켜서 메모리에 데이터가 올라온 상태에서 '$'로 혹은 transform() 함수로 데이터 객체를 변경하였다면 detach() 로 활성화를 해제시켰다가 다시 attach()로 활성화 시켜서 사용할 것.

> # cust_id, last_nm, age 세개의 벡터 생성
> cust_id <- c(1, 2, 3)
> last_nm <- c("Kim", "Lee", "Park")
> age <- c(20, 25, 29)
>

> # profile 이라는 데이터 프레임으로 cust_id, last_nm, age 세개 벡터 묶기 > profile <- data.frame(cust_id, last_nm, age) > profile cust_id last_nm age 1 1 Kim 20 2 2 Lee 25 3 3 Park 29

>

> # The following objects are masked _by_ .GlobalEnv: 안뜨게 하려면 삭제

> rm(cust_id, last_nm, age)  
>

>

> # attach()로 활성화

> attach(profile)

> age [1] 20 25 29 >

> # '$'로 profile 데이터 프레임을 지정하여 age 변수에 새로운 값 할당 (날씨 10살씩 더한 값)

> profile$age <- c(30, 35, 39) > profile # 새로운 age 값이 뜸 (원본 데이터는 변경되었음!!!!) cust_id last_nm age 1 1 Kim 30 2 2 Lee 35 3 3 Park 39

 

 

>

> # 그런데 attach()로 메모리에 불려들였던 'age'는 변하지 않은 이전 값임(주의 요망!!!!!)

> age [1] 20 25 29 >

> # 원본 데이터(변경 후)와 attach()로 메모리에 상주된 동일 변수 데이터가 값이 다르므로 주의요망

> # 해결 방법은 detach()로 메모리 상주(활성화) 해제 하고 attach()로 새로 활성화 시키면 됨

> detach(profile) > attach(profile) > age # 새로 변경한 값이 뜸 [1] 30 35 39 > detach(profile)

 

 

 

이번 포스팅 내용은 좀 어려울 것 같습니다. 저게 무슨 소리인가, 말인가 막걸리인가...그게 그 소리 같고... 헷갈리는 내용이지만 attach(), detach()는 아마 자주 사용하는 함수일터이니 제대로 알고 사용해야 에러를 피해갈 수 있겠지요?!

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡' 단추를 꾸욱 눌러주세요.^^

 

728x90
반응형
Posted by Rfriend
,