R에서 특정 조건을 만족하는지의 조건을 주고 뒤에 이어지는 표현식을 반복적으로 수행하게 하는 조건 연산 프로그래밍에 대해 알아보겠습니다.

 

 

 

먼저 한개의 숫자형 값에 대해 이것이 짝수인지 홀수인지 판단하는 R program을 짜보도록 하겠습니다.

 

 

 

 


  • 하나의 값에 대한 판단인 경우 : 

    if( 조건1 ) {
              표현식 1
    } else if (조건2) {
              표현식 2
    } else {
              표현식 3
    }

  

[ 짝수, 홀수 여부 판단 프로세스 ]

 

 

(1) 하나의 논리값에 대한 판단인 경우 : if()

 

> ## 하나의 논리값에 대한 판단
> # if()
> x1 <- c(4)
> if (x1 %% 2 == 0) {
+   y1 = c("Even Number")
+   print(y1)
+ } else {
+     y1 = c("Odd Number")
+     print(y1)
+ }
[1] "Even Number"

 

 

> x2 <- c(5)
> if (x2 %% 2 == 0) {
+   y2 = "Even Number"
+   print(y2)
+ } else {
+   y2 = "Odd Number"
+   print(y2)
+ }
[1] "Odd Number"
 

위의 2개의 예에서는 x1 이 4일 때 "Even Number"라고 판단했고, x2가 5일 때 "Odd Number"라고 잘 판단하였습니다.

 

하지만, 아래의 예제처럼 두개 이상의 논리값 벡터를 사용하는 경우에는 오류가 발생하게 되며, 아래 예제에서 보면 1~5까지 숫자 중에서 제일 처음으로 나오는 1에만 아래의 조건연산 프로그램이 적용되었고 두번째부터는 적용이 안되었습니다.  이럴 때는 ifelse() 문을 사용하여야 합니다

 

> # Error
> x3 <- c(1, 2, 3, 4, 5)
> if (x3 %% 2 == 0) {
+   y3 = "Even Number"
+   print(y3)
+ } else {
+   y3 = "Odd Number"
+   print(y3)
+ }
[1] "Odd Number"
Warning message:
In if (x3%%2 == 0) { :
  the condition has length > 1 and only the first element will be used

 



 

(2) 두개 이상의 논리값 벡터에 대한 판단 : ifelse()

 

  • 두개 이상의 논리값 벡터에 대한 판단인 경우 :

    ifelse( 조건1, 표현식1, 
          ifelse( 조건2, 표현식2, 
                 ifelse( 조건3, 표현식3, 표현식4)
                 ) 
           )
  •  

    위와 동일하게 1~5의 숫자에 대해서 이번에는 ifelse() 문을 사용해서 짝수, 홀수 여부를 판단하게 하고, 이를 데이터프레임 구조로 변환해서 view해보겠습니다.

     

    > ## vector 에 대한 판단
    > # 홀수/짝수 여부 판단 : ifelse( condition, expression 1, expression 2 )
    > x <- c(1, 2, 3, 4, 5)
    > z <- ifelse(x%%2 == 0, "Even Number", "Odd Number")
    > xz <- data.frame(x, z)
    > xz
      x           z
    1 1  Odd Number
    2 2 Even Number
    3 3  Odd Number
    4 4 Even Number
    5 5  Odd Number

     

     

     


     

     

    이번에는 양수, 0, 음수 인지 여부를 판단한 후 원래 벡터와 판단하는 프로그램을 ifelse()를 사용하여 짜보도록 하겠습니다.

     

    [ 양수, 0, 음수 인지 여부 판단하는 프로세스 ]

     

     

    > # 양수, 0, 음수인지 여부 판단 : ifelse( condition, expression 1, expression 2 ) > x <- c(-2, -1, 0, 1, 2) > y <- ifelse( x > 0, "Positive", + ifelse( x == 0, "Zero", "Negative") + ) > > xy <- data.frame(x, y) > > xy x y 1 -2 Negative 2 -1 Negative 3 0 Zero 4 1 Positive 5 2 Positive 

     

     


     

    To 산낙지님,

    제가 가족 여행다녀오느라 이제서야 집에 와서 댓글 달려고 막 하는 와중에...댓글을 삭제하셨네요. ^^;

    3가지 조건을 주어서 1, 0 혹은 yes, no 범주형 dummy 변수를 생성하는 방법은 아래를 참고하세요.

    MASS 패키지의 Cars93데이터프레임을 가지고 예를 들었습니다.

    [예제] "차종(Type)이 "Campact" 이고 & 가격(Price)이 16이하이고 & 고속도로연비(MPG.highway)가 30이상이면 1, 그 외는 모두 0인 변수 sub_yn 을 만드시오"

    ## Making dummy variable using ifelse() and transform()
    library(MASS)
    str(Cars93)
    summary(Cars93$Price)
    summary(Cars93$MPG.highway)

    Cars93 <- transform(Cars93,
                               sub_yn = ifelse(Type == c("Compact")
                                                   & Price <= 16
                                                   & MPG.highway >= 30, 1, 0))

     

     

     

     

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

     

     

    Posted by R Friend R_Friend

    댓글을 달아 주세요

    1. R Friend R_Friend 2016.10.03 19:03 신고  댓글주소  수정/삭제  댓글쓰기

      To 산낙지님,

      제가 가족 여행다녀오느라 이제서야 집에 와서 댓글 달려고 막 하는 와중에...댓글을 삭제하셨네요. ^^;

      3가지 조건을 주어서 1, 0 혹은 yes, no 범주형 dummy 변수를 생성하는 방법은 아래를 참고하세요.

      MASS 패키지의 Cars93데이터프레임을 가지고 예를 들었습니다.

      [예제] "차종(Type)이 "Campact" 이고 & 가격(Price)이 16이하이고 & 고속도로연비(MPG.highway)가 30이상이면 1, 그 외는 모두 0인 변수 sub_yn 을 만드시오"

      ## Making dummy variable using ifelse() and transform()
      library(MASS)
      str(Cars93)
      summary(Cars93$Price)
      summary(Cars93$MPG.highway)

      Cars93 <- transform(Cars93,
      sub_yn = ifelse(Type == c("Compact")
      & Price <= 16
      & MPG.highway >= 30, 1, 0))

      • 산낙지 2016.10.03 20:24  댓글주소  수정/삭제

        아 제가 방명록에 다시 달려고 댓글을 삭제했는데 여기에 달으셨군요 ^^; 댓글 삭제해서 죄송하고 답변 정말 감사합니다~~ 많은 참고 하겠습니다!

    2. 정현복 2017.01.06 17:56  댓글주소  수정/삭제  댓글쓰기

      a=c(1,2,NA,NA,3,5)
      b=c(2,4,5,6,7,8)
      ab=cbind(a,b)
      ab=as.data.frame(ab)
      class(ab)

      if (is.na(ab$a)=TRUE) ab$a=0 else ab$a=1
      if (is.na(ab$a)) ab$a=0 else ab$a=1
      if(ab$a==NA) {ab$a=0} else {ab$a=1}
      ab$a=ifelse(is.na(ab$a),0,1)

      안녕하세요 제가 코딩을 해보가 if문을 사용하는데 아무리 고쳐보고 책찾아보고 해도 도대체 왜 않되는지 모르겠습니다 맨마지막 코딩은 비로서 실행이 되는데 저거는 실행이 된다면 그러면 위에 if문들은 왜 않되는건지 도저히 이해가 않됩니다 도와주세요 ㅠㅠ

    3. 정현복 2017.01.09 23:54  댓글주소  수정/삭제  댓글쓰기

      글쓴이분 정말감사해요
      근데 1가지 정말 해결해주실수 잇나요
      데이터 테이블인데 지금
      gender변수안에 m f 가 팩터로 들어가 있는데 저는 그 변수값을 m이면 1 f면 0으로 넣고싶은데 어떻게 해야 할까요 이것도 찾아보고 저것도 찾아보고 3시간넘게 사투중인데 공모전 준비하는데 ㅠㅠ
      너무 힘들어요 아진짜 ㅠㅠㅠ제발 도와주세요 ㅠㅠ

      • R Friend R_Friend 2017.01.10 00:33 신고  댓글주소  수정/삭제

        정현복님, transform()과 elif() 함수가지고 간단한 예제 R script 짜보았습니다. 참고하세요.

        # making an example dataframe
        cust_id <- c(1, 2, 3, 4, 5, 6)
        gender <- c("F", "M", "F", "F", "M", "F")
        age <- c(23, 28, 42, 34, 45, 36)

        cust_df <- data.frame(cust_id, gender, age)

        # data structure check
        str(cust_df)

        # transforming by ifelse() function
        cust_df <- transform(cust_df, gender_new = ifelse(gender == "M", 1, 0))

        cust_df

        # 참고 포스팅
        http://rfriend.tistory.com/38

    R이 통계분석 툴이자 그래픽을 위한 훌륭한 툴이면서도, 동시에 프로그래밍 언어(programming language)로서도 매우 훌륭하답니다.  반복적인 작업(Loop process)을 해야 하는 경우나, 분석가가 알고리즘을 만들어서 자동화할 수 있는 사용자 정의 함수(User defined function) 를 잘 사용한다면 소위 말하는 시간 잡아먹는 노가다를 컴퓨터에게 대신 시킬 수 있게 됩니다. 

     

    손발이 편하고 싶고, 귀한 시간을 아끼고 싶다면 R 프로그래밍에 대해 익혀두는게 유용할 것입니다.  게다가, R이 데이터 변환/처리/분석/그래프 까지 두루 섭렵하고 있다보니 "데이터 기반의 프로그래밍"이 필요한 일이라면 R이 제격이라고 하겠습니다.

     

    이번 포스팅에서는 for()와 while() 함수를 사용하여 반복 연산 프로그래밍 (Loop process programming) 하는 방법을 몇 개 예를 들어 소개하겠습니다.

     

     

    [ Loop Process Diagram ]

     

     

     

     

    (1) y= 10 + 5*x 함수에 x를 1부터 10까지 1씩 더해가면서 연산하고 y값을 순차적으로 프린트

         : for (var in seq) {expression}

     

    > # x 1:10, y = 10 + 5*x
    > for ( x in 1:10) {
    +   y = 10 + 5*x
    +   print(y)
    + }
    [1] 15
    [1] 20
    [1] 25
    [1] 30
    [1] 35
    [1] 40
    [1] 45
    [1] 50
    [1] 55
    [1] 60 

     

     

    (2) 1~10까지의 1씩 늘려가면서 누적합 구하고, 순차적으로 프린트하기

        : for (var in seq) {expression}

     

     
    > # 1~10까지 누적합 구하기 (cummulative sum by for) : for (var in seq) { expression }
    > y <- 0
    > for(i in 1:10) {
    +      y = y + i
    +      cat("cummulative summation from 0 to ", i, " is ", y, "\n", sep="")
    +    }
    cummulative summation from 0 to 1 is 1
    cummulative summation from 0 to 2 is 3
    cummulative summation from 0 to 3 is 6
    cummulative summation from 0 to 4 is 10
    cummulative summation from 0 to 5 is 15
    cummulative summation from 0 to 6 is 21
    cummulative summation from 0 to 7 is 28
    cummulative summation from 0 to 8 is 36
    cummulative summation from 0 to 9 is 45
    cummulative summation from 0 to 10 is 55
     

     

    참고로, cat 은 텍스트를 받아다가 콘솔에 프린트해주는 기능을 합니다.

    "\n" 은 줄바꿈 설정하는 파라미터입니다.

    sep="" 는 cat() 함수 안에 큰따옴표로 들어가 있는 텍스트 문자열 혹은 'i', 'z' 객체를 연결할 때 구분자를 지정해주는 것입니다. sep="" 이므로 아무것도 없이 그냥 붙여서 연결시키라는 뜻이구요, 만약 sep="__" 라고 under-bar 2개로 지정해주면 첫번째 줄이

    cummulative summation from 0 to __1__ is __1

    처럼 프린트 되었을 것입니다.

     

     

     

    (3) 1~10까지의 1씩 늘려가면서 누적합 구하고, 순차적으로 프린트하기

        : while (condition) {expression}

     

    while() 문은 조건을 걸고 싶거나 반복회수를 미리 파악하기 어려운 경우에 사용하면 유용합니다.

     

     
    > # 1~10까지 누적합 구하기 (cummlative sum by while) : while(condition) { expression }
    > z <- 0
    > i <- 1
    > while( i <= 10) {
    +      z = z + i
    +      cat("cummulative summation from 0 to ", i, " is ", z, "\n", sep="") 
    +      i = i + 1
    +    }
    cummulative summation from 0 to 1 is 1
    cummulative summation from 0 to 2 is 3
    cummulative summation from 0 to 3 is 6
    cummulative summation from 0 to 4 is 10
    cummulative summation from 0 to 5 is 15
    cummulative summation from 0 to 6 is 21
    cummulative summation from 0 to 7 is 28
    cummulative summation from 0 to 8 is 36
    cummulative summation from 0 to 9 is 45
    cummulative summation from 0 to 10 is 55
     

     

     

     


     

     

    예를 들어, 1부터 시작해서 1씩 늘려가면서 3을 더해가는 것(y = y + 3)을 반복하는데, 단 5 이하일 때까지만 반복시키는 조건이 있을 때,

     - while(condition)

     - while(TRUE/FALSE) { if () break }

     - repeat { if () break }

    의 3가지 방법을 알아보겠습니다.  아래의 (4) ~ (6)번 프로그래밍 예제는 로직과 결과가 동일합니다.

     

    (4) while(condition)

     

    > # while(condition) => stop
    > i <- 1
    > while( i <= 5 ) {
    +   i <- i+3
    + }
    > 
    > i
    [1] 7 

     

     

     

    (5) while(TRUE/FALSE) { if () break }

     

    > # while(TRUE/FALSE) { if () break } => stop
    > j <- 1
    > while(TRUE) {
    +   j <- j+3
    +   if (j > 5) break
    + }
    > 
    > j
    [1] 7

     

    처음에 j <- 1로 할당되었습니다. 

    그 다음에 while() 문으로 넘어가서요, j <- j+3 이므로 j <- 1+3 가 되어서 j에 4가 새로 할당(덮어쓰기)이 되었습니다.  if (j > 5) break 인데요, 여기서 j는 4이므로 if (j > 5) 조건에서 FALSE 가 됩니다. 따라서 break하지 않고 loop 를 계속 돌게 됩니다(not break, but continue loop). 

    그럼 다시 j <- j+3 으로 돌아가서 다시 연산을 수행합니다. 방금 전 연산에서 j가 4로 재할당 되었었지요? 그러므로 j+3 = 4+3 = 7로서 j에 7이 재할당 (덮어쓰기) 됩니다.

    if (j > 5) 조건에서 if (7 > 5) 로서 TRUE 가 되었으므로 break 하게 됩니다.

    j 를 프린트해보면 '7'이 됩니다.

     

     

     

    (6) repeat { if () break }

     

    > # repeat { if () break } => stop > k <- 1 > repeat { + k <- k+3 + if (k > 5) break + } > > k [1] 7

     

     

    위의 (5)번, (6)번 예에서 보면 while 문에는 TRUE/FALSE 의 불리언 상태값이 있습니다만, repeat 문에는 불리언 상태값 없이 break 를 사용해서 조건을 만족하면 반복을 중지시키는 차이점이 있습니다.

     

     

     


     

    아래의 프로그램 예는 repeat 함수를 이용해서 factorial(i) 값이 1,000,000,000,000 보다 작을 때까지는 계산 순차적으로 1씩 i를 증가시켜가면서 계산을 하고 프린트를 하다가, 1조보다 커지면 stop하라는 명령문입니다.

     

     
    > i <- 1
    > repeat {
    +   factorial_value <- factorial(i)
    +   cat("factorial(", i, ") = ", factorial_value, "\n", sep="")
    +   if (factorial_value > 1000000000000) break
    +   i <- i+1
    + }
    factorial(1) = 1
    factorial(2) = 2
    factorial(3) = 6
    factorial(4) = 24
    factorial(5) = 120
    factorial(6) = 720
    factorial(7) = 5040
    factorial(8) = 40320
    factorial(9) = 362880
    factorial(10) = 3628800
    factorial(11) = 39916800
    factorial(12) = 479001600
    factorial(13) = 6227020800
    factorial(14) = 87178291200
    factorial(15) = 1.307674e+12

     

     

     

     

    factorial(i) 값이 '0'이 100개 붙은 값(우리나라말로 이걸 명칭하는 단위가 없죠? 어마무시 큰 수? ^^')보다 작으면 계속 i 값을 1씩 증가시키면서 계산하다가, '0'이 100개 붙은 값보다 커지면 stop 하라는 명령문은 아래와 같습니다.

     

    > i <- 1
    > repeat {
    +   factorial_value <- factorial(i)
    +   cat("factorial(", i, ") = ", factorial_value, "\n", sep="")
    +   if (factorial_value > 1e+100) break
    +   i <- i+1
    + }
    factorial(1) = 1
    factorial(2) = 2
    factorial(3) = 6
    factorial(4) = 24
    factorial(5) = 120
    factorial(6) = 720
    factorial(7) = 5040
    factorial(8) = 40320
    factorial(9) = 362880
    factorial(10) = 3628800
    factorial(11) = 39916800
    factorial(12) = 479001600
    factorial(13) = 6227020800
    factorial(14) = 87178291200
    factorial(15) = 1.307674e+12
    factorial(16) = 2.092279e+13
    factorial(17) = 3.556874e+14
    factorial(18) = 6.402374e+15
    factorial(19) = 1.216451e+17
    factorial(20) = 2.432902e+18
    factorial(21) = 5.109094e+19
    factorial(22) = 1.124001e+21
    factorial(23) = 2.585202e+22
    factorial(24) = 6.204484e+23
    factorial(25) = 1.551121e+25
    factorial(26) = 4.032915e+26
    factorial(27) = 1.088887e+28
    factorial(28) = 3.048883e+29
    factorial(29) = 8.841762e+30
    factorial(30) = 2.652529e+32
    factorial(31) = 8.222839e+33
    factorial(32) = 2.631308e+35
    factorial(33) = 8.683318e+36
    factorial(34) = 2.952328e+38
    factorial(35) = 1.033315e+40
    factorial(36) = 3.719933e+41
    factorial(37) = 1.376375e+43
    factorial(38) = 5.230226e+44
    factorial(39) = 2.039788e+46
    factorial(40) = 8.159153e+47
    factorial(41) = 3.345253e+49
    factorial(42) = 1.405006e+51
    factorial(43) = 6.041526e+52
    factorial(44) = 2.658272e+54
    factorial(45) = 1.196222e+56
    factorial(46) = 5.502622e+57
    factorial(47) = 2.586232e+59
    factorial(48) = 1.241392e+61
    factorial(49) = 6.082819e+62
    factorial(50) = 3.041409e+64
    factorial(51) = 1.551119e+66
    factorial(52) = 8.065818e+67
    factorial(53) = 4.274883e+69
    factorial(54) = 2.308437e+71
    factorial(55) = 1.26964e+73
    factorial(56) = 7.109986e+74
    factorial(57) = 4.052692e+76
    factorial(58) = 2.350561e+78
    factorial(59) = 1.386831e+80
    factorial(60) = 8.320987e+81
    factorial(61) = 5.075802e+83
    factorial(62) = 3.146997e+85
    factorial(63) = 1.982608e+87
    factorial(64) = 1.268869e+89
    factorial(65) = 8.247651e+90
    factorial(66) = 5.443449e+92
    factorial(67) = 3.647111e+94
    factorial(68) = 2.480036e+96
    factorial(69) = 1.711225e+98
    factorial(70) = 1.197857e+100

     

     

    많은 도움 되었기를 바랍니다.

     

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

     

     

    Posted by R Friend R_Friend

    댓글을 달아 주세요

    1. kjh 2016.09.16 17:14  댓글주소  수정/삭제  댓글쓰기

      한 데이터셋에 있는 각 열별 NA 개수를 출력하는 반복문을 만들려고 하는데요
      for(i in 1:length(CLAIM)){
      sum(is.na(CLAIM[i]))
      }

      저는 CLAIM이라는 데이터셋을 사용했는데..
      R Studio가 아무것도 안해줍니다 ㅠㅠ
      제 명령을 씹어요..
      length(CLAIM)도 제대로 동작하고
      sum(is.na(CLAIM[3]) 이런식으로 숫자를 넣어봐도 제대로 동작하는걸 확인했는데
      for는 먹통이네요.. 왜그럴까요? 출력을 안해줘요 오류도 안뜨구요.

      • R Friend R_Friend 2016.09.16 17:52 신고  댓글주소  수정/삭제

        kjh님,
        원하시는 실행은 아래처럼 colSums(is.na(dataframe)) 함수를 사용하시면 됩니다.

        colSums(is.na(CLAIM))


        루프문에 칼럼 이름별로 결측값 개수를 개별 변수이름별로 할당하려면 아래 링크 assign()함수 참고하세요. 제가 시골 내려와있는데 컴퓨터를 사용할수 없어서 길게는 못쓰겠네요.

        assign()함수
        http://rfriend.tistory.com/m/108

    2. 2017.03.18 21:26  댓글주소  수정/삭제  댓글쓰기

      비밀댓글입니다

      • R Friend R_Friend 2017.03.18 21:48 신고  댓글주소  수정/삭제

        안녕하세요.

        (1) cat 은 텍스트를 받아다가 콘솔에 프린트해주는 기능을 합니다.

        "\n" 은 줄바꿈 설정하는 파라미터입니다.

        sep="" 는 cat() 함수 안에 큰따옴표로 들어가 있는 텍스트 문자열 혹은 'i', 'z' 객체를 연결할 때 구분자를 지정해주는 것입니다. sep="" 이므로 아무것도 없이 그냥 붙여서 연결시키라는 뜻이구요, 만약 sep="__" 라고 under-bar 2개로 지정해주면 첫번째 줄이

        cummulative summation from 0 to __1__ is __1

        처럼 프린트 되었을 것입니다.

        (2) while() 문은 TRUE/FALSE 불리언 조건이 만족할 때까지 반복작업을 수행하게 됩니다.

        따라서 (5) 번 예제를 예로 들어 설명해보면요,

        처음에 j <- 1로 할당되었습니다.

        그 다음에 while() 문으로 넘어가서요, j <- j+3 이므로 j <- 1+3 가 되어서 j에 4가 새로 할당(덮어쓰기)이 되었습니다. if (j > 5) break 인데요, 여기서 j는 4이므로 if (j > 5) 조건에서 FALSE 가 됩니다. 따라서 break하지 않고 loop 를 계속 돌게 됩니다(not break, but continue loop).

        그럼 다시 j <- j+3 으로 돌아가서 다시 연산을 수행합니다. 방금 전 연산에서 j가 4로 재할당 되었었지요? 그러므로 j+3 = 4+3 = 7로서 j에 7이 재할당 (덮어쓰기) 됩니다.

        if (j > 5) 조건에서 if (7 > 5) 로서 TRUE 가 되었으므로 break 하게 됩니다.

        j 를 프린트해보면 '7'이 됩니다.


        블로그 글 좋게 봐주셔서 감사합니다. ^^

    3. 2017.03.25 16:34  댓글주소  수정/삭제  댓글쓰기

      비밀댓글입니다

      • R Friend R_Friend 2017.03.27 19:51 신고  댓글주소  수정/삭제

        벡터끼리의 논리 연산의 경우 loop 문을 안써도 알아서 순환하면서 벡터 내 원소끼리 비교를 해서 TRUE, FALSE를 반환해 줍니다. 가령,

        (1) 두 벡터의 원소의 개수가 같을 경우 논리 연산

        a <- c(1, 2, 3, 4, 5)
        b <- c(0, -1, 4, 4, 10)

        a >= b

        TRUE TRUE FALSE TRUE FALSE
        를 반환합니다.

        (2) 두 벡터의 원소 개수가 다를 경우 : 원소 개수가 작은 쪽이 순서대로 broadcasting 을 해서 알아서 짝을 맞추어서 논리 연산을 수행 (단, 벡터의 원소 개수(길이)가 서로 다르다고 경고 메시지가 빨간 색으로 뜸)

        a <- c(1, 2, 3, 4, 5)
        c <- c(-5, 4, 1)

        a >= c

        TRUE FALSE TRUE TRUE TRUE

    4. 폴짝이 2019.08.10 21:41  댓글주소  수정/삭제  댓글쓰기

      R 데이터 분석을 하는데
      양적변수와 양적변수를 비교하려는 그래프를 그리려는데 변수가 많은데.. 어떻게 표현해야하는지 모르겠습니다,

      • R Friend R_Friend 2019.08.10 23:00 신고  댓글주소  수정/삭제

        정확한 요건이 무엇인지 몰라 좀 애매하긴 한데요, 아래의 클리브랜드 점 그래프 한번 참고해보세요.

        https://rfriend.tistory.com/75

        ggplot2의 facet_grid 옵션도 참고하세요.

        for loop 이나 혹은 사용자 정의함수도 한번 고려해볼 수 있겠구요.

        R Shiny로 interactive plot 도 생각해볼 수 있겠네요.

    그동안 R로 다양한 그래프를 그리는 방법을 알아보았습니다.  R로 그래프를 그렸다면, 보는 이의 가독성, 해석의 용이성을 높여주기 위해서 그래프 위에 텍스트, 가로선/세로선/대각선, 화살표, 음영 사각형, 제목 등과 같이 추가로 정보를 제공하거나 강조를 하고 싶은 부분에 주석을 달고 싶을 때가 있습니다.

     

     

    - 텍스트 : annotate("text")

     

    - 가로선/세로선/대각선 : geom_vline(), geom_hline(), geom_abline()

     

    - 화살표 : annotate("segment", arrow=arrow()) , with grid package


    - 음영 사각형 : annotate("rect")


    - 제목 : ggtitle()

     

     

    매번의 R 그래프/시각화 포스팅마다 주석 다는 방법을 간간이 곁들여서 소개해드리기는 했는데요, 이번 포스팅에서는 주석 다는 방법에 대해서 포괄적이고 종합적으로 정리를 해서 바로 찾아보기 편하도록 정리를 해보았습니다.

     

     

    예제로 사용할 데이터는 Base Package에 내장되어 있는 iris 데이터 프레임의 Petal.Width, Petal.Length, Species 의 세개 변수를 사용하겠습니다. (iris 데이터셋은 데이터 마이닝 실습에 아주 많이 사용되는 데이터셋으로서, iris 꽃 품종 중 setosa 50개, versicolor 50개, virginica 50개를 꽃잎의 넓이와 길이를 측정해놓은 데이터셋입니다)

     

     

     

    > str(iris)
    'data.frame':	150 obs. of  5 variables:
     $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
     $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
     $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
     $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
     $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ... 

     

     

    ggplot2는 별도의 설치 및 호출이 필요한 패키지이므로 아래의 절차를 먼저 실행하시기 바랍니다.

     

    > install.packages("ggplot2")
    Installing package into ‘C:/Users/user/Documents/R/win-library/3.2’
    (as ‘lib’ is unspecified)
    trying URL 'http://cran.rstudio.com/bin/windows/contrib/3.2/ggplot2_1.0.1.zip'
    Content type 'application/zip' length 2676992 bytes (2.6 MB)
    downloaded 2.6 MB
    
    package ‘ggplot2’ successfully unpacked and MD5 sums checked
    
    The downloaded binary packages are in
    	C:\Users\user\AppData\Local\Temp\RtmpEfAwCj\downloaded_packages
    > library(ggplot2) 

     

    (1) iris의 Petal.Width를 x축으로, Petal.Length를 y축으로 하고, 품종(Species)에 따라서 색깔을 달리해서 산포도(scatter plot)을 그려보겠습니다.

     

    > # scatter plot of iris dataset
    > a1 <- ggplot(iris, aes(x=Petal.Width, y=Petal.Length, fill=Species)) + 
    +   geom_point(colour="grey", shape=21, size=6) +
    +   scale_fill_brewer(palette="Reds")
    > 
    > a1
     

     

     

     

     

    (2) 텍스트(text) 추가 : annotate("text")

     

    > # 텍스트(text) 추가 : annotate("text")
    > 
    > a2 <- a1 + 
    +   annotate("text", x=0.25, y=2.4, label="Setosa", size=7) + # text annotation
    +   annotate("text", x=1.3, y=3.3, label="Versicolor", size=7) + 
    +   annotate("text", x=1.7, y=6.8, label="Virginica", size=7)
    > 
    > a2

     

     

     

     

     

     

    (3) 선(line) 추가 : geom_vline(), geom_hline(), geom_abline()

     

    > # 선(line) 추가 : geom_vline(), geom_hline(), geom_abline()
    > 
    > a3 <- a2 + 
    +   geom_hline(yintercept=2.6, colour="grey", lty="dashed", size=1) + # horizontal line
    +   geom_hline(yintercept=4.9, colour="grey", lty="dashed", size=1) + 
    + 
    +   geom_vline(xintercept=0.8, colour="grey", lty="dashed", size=1) + # vertical line
    +   geom_vline(xintercept=1.75, colour="grey", lty="dashed", size=1) + 
    +   
    +   geom_abline(intercept=8, slope=-2.1, colour="red", lty="dotted", size=1.5) # abline
    >   
    > a3

     

     

     

     

     

    (4) 화살표(arrow) 추가 : annotate("segment")

     

    단, grid 패키지를 호출해서 사용해야 합니다.

     

    > # 화살표(arrow) 추가 : annotate("segment")
    > library(grid) # grid 패키지 호출
    > 
    > a4 <- a3 + 
    +   annotate("segment", x=2, xend=2.1, y=2, yend=3.5, size=1.5, colour="red", arrow=arrow())
    > 
    > a4
    > 
    > 
    > # 텍스트 추가 : annotate("text")
    > a5 <- a4 + 
    +   annotate("text", x=2, y=1.8, size=6, colour="red", label="y=8 - 2.1x")
    > 
    > a5

     

     

     

     

     

     

     

    (5) 음영 사각형(shadowed box) 추가 : annotate("rect")

     

    > # 음영 사각형(shadowed box) 추가 : annotate("rect")
    > a6 <- a5 + 
    +   annotate("rect", xmin=0, xmax=0.8, ymin=0, ymax=2.6, alpha=0.1, fill="red") + 
    +   annotate("rect", xmin=0.8, xmax=1.75, ymin=2.6, ymax=4.9, alpha=0.2, fill="red") + 
    +   annotate("rect", xmin=1.3, xmax=2.7, ymin=4.3, ymax=7.2, alpha=0.3, fill="red")
    > 
    > a6

     

     

     

     

     

    (6) 제목(title) 추가 : ggtitle()

     

    > # 제목 추가 : ggtitle()
    > 
    > a7 <- a6 + 
    +   ggtitle("Annotation of Text, Line, Arrow, Shadowed Box, Title")
    > 
    > a7

     

     

     

     

    많은 도움 되었기를 바랍니다.

     

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

     

    Posted by R Friend R_Friend

    댓글을 달아 주세요

    이번 포스팅에서는 R ggplot2에서 그래프 색깔 설정 (colour setting), 조절하는 방법에 대해서 알아보겠습니다.  이전의 각 그래프 종류별로 소개한 내용에도 색깔 지정에 대한 내용이 조금씩 포함되어 있기는 합니다만, 이번 포스팅에서는 색깔 설정에 대한 경우의 수를 종합적으로 포괄해서 정리를 해보았습니다.

     

    그래프에서 색깔을 특정 변수의 변화와 align하게 되면 x축과 y축의 2차원에 색깔이라는 차원을 추가함으로써 3차원의 정보를 제공할 수 있습니다.  회사 업무 보고서에 엑셀로 그린 그래프를 많이 사용하고는 하는데요, x축과 y축의 2차원을 넘어서는, 특정 조건에 따라서 색깔이나 모양을 달리해야 하는 경우라면 엑셀로 그래프를 그리는 것이 거의 불가능하게 됩니다.  이때 R이 데이터 전처리/변환부터 해서 인쇄용으로 바로 사용해도 좋을 만큼의 고품질의 그래프를 그리는데 아주 특출난 역할을 할 수 있습니다.  R 그래프에서 색깔을 자유자재로 사용할 수 있다면 미적으로도 보기에 좋겠지요?!

     

     

    이번 예제에서 사용할 데이터는 MASS 패키지에 내장되어 있는 Cars93 데이터 프레임의 차 무게(Weight)와 고속도로연비(MPG.highway), 차 가(Price), 실린더 개수(Cylinders)의 4개 변수를 사용하겠습니다.

     

    > library(MASS)
    > str(Cars93)
    'data.frame':	93 obs. of  27 variables:
     $ Manufacturer      : Factor w/ 32 levels "Acura","Audi",..: 1 1 2 2 3 4 4 4 4 5 ...
     $ Model             : Factor w/ 93 levels "100","190E","240",..: 49 56 9 1 6 24 54 74 73 35 ...
     $ Type              : Factor w/ 6 levels "Compact","Large",..: 4 3 1 3 3 3 2 2 3 2 ...
     $ Min.Price         : num  12.9 29.2 25.9 30.8 23.7 14.2 19.9 22.6 26.3 33 ...
     $ Price             : num  15.9 33.9 29.1 37.7 30 15.7 20.8 23.7 26.3 34.7 ...
     $ Max.Price         : num  18.8 38.7 32.3 44.6 36.2 17.3 21.7 24.9 26.3 36.3 ...
     $ MPG.city          : int  25 18 20 19 22 22 19 16 19 16 ...
     $ MPG.highway       : int  31 25 26 26 30 31 28 25 27 25 ...
     $ AirBags           : Factor w/ 3 levels "Driver & Passenger",..: 3 1 2 1 2 2 2 2 2 2 ...
     $ DriveTrain        : Factor w/ 3 levels "4WD","Front",..: 2 2 2 2 3 2 2 3 2 2 ...
     $ Cylinders         : Factor w/ 6 levels "3","4","5","6",..: 2 4 4 4 2 2 4 4 4 5 ...
     $ EngineSize        : num  1.8 3.2 2.8 2.8 3.5 2.2 3.8 5.7 3.8 4.9 ...
     $ Horsepower        : int  140 200 172 172 208 110 170 180 170 200 ...
     $ RPM               : int  6300 5500 5500 5500 5700 5200 4800 4000 4800 4100 ...
     $ Rev.per.mile      : int  2890 2335 2280 2535 2545 2565 1570 1320 1690 1510 ...
     $ Man.trans.avail   : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 1 1 1 1 1 ...
     $ Fuel.tank.capacity: num  13.2 18 16.9 21.1 21.1 16.4 18 23 18.8 18 ...
     $ Passengers        : int  5 5 5 6 4 6 6 6 5 6 ...
     $ Length            : int  177 195 180 193 186 189 200 216 198 206 ...
     $ Wheelbase         : int  102 115 102 106 109 105 111 116 108 114 ...
     $ Width             : int  68 71 67 70 69 69 74 78 73 73 ...
     $ Turn.circle       : int  37 38 37 37 39 41 42 45 41 43 ...
     $ Rear.seat.room    : num  26.5 30 28 31 27 28 30.5 30.5 26.5 35 ...
     $ Luggage.room      : int  11 15 14 17 13 16 17 21 14 18 ...
     $ Weight            : int  2705 3560 3375 3405 3640 2880 3470 4105 3495 3620 ...
     $ Origin            : Factor w/ 2 levels "USA","non-USA": 2 2 2 2 2 1 1 1 1 1 ...
     $ Make              : Factor w/ 93 levels "Acura Integra",..: 1 2 4 3 5 6 7 9 8 10 ... 

     

    ggplot2 패키지는 별도의 설치 및 호출이 필요하므로 아래의 절차를 먼저 시행합니다.

     

    > install.packages("ggplot2") # 설치

    > library(ggplot2)  

     

     

    색상 변화를 잘 살펴볼 수 있도록 속이 빈 동그라미 모양인 shape=21 번의 도형을 사용해서 size=6 으로 큼지막하게 키워서 예를 들어보겠습니다. 

     

     

    (1) 색깔 설정을 별도로 하지 않은 경우 디폴트 테두리 검정색 (default colour)

     

    > # default colour
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway)) +
    +   geom_point(shape=21, size=6)

     

     

     

     

     

    (2) 테두리 선 색깔 지정 (colour : line colour setting)

     

    > # 테두리 선 색깔 지정 (colour : line colour setting)
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway)) +
    +   geom_point(shape=21, size=6, colour="blue")

     

     

     

     

     

     

    (3) 도형의 속 채우기 색깔 지정 (fill : innner colour fill-up)

     

    > # 도형의 속 채우기 색깔 (fill : inner colour fill-up)
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway)) +
    +   geom_point(shape=21, size=6, fill="blue")

     

     

     

     

     

     

    (4) 연속형 변수의 숫자에 따른 색깔 조절 : aes(fill=continuous variable)

     

    > # 연속형 변수의 숫자에 따른 색깔 조절
    > # (fill : colour change aligned with continuous numeric variable)
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway, fill=Price)) +
    +   geom_point(colour="grey", shape=21, size=6)

     

     

     

     

     

     

    (5) 범주형 변수의 범주/요인(factor)에 따른 색깔 조절 : aes(fill=categorical variable)

     

    > # 범주형 변수의 범주/요인(factor) 따른 색깔 조절 
    > # (fill : colour change aligned with categorical variable)
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway, fill=Cylinders)) +
    +   geom_point(colour="grey", shape=21, size=6)

     

     

     

     

     

    ###  아래의 palette 설정은 범주형 데이터 (categorical data)에만 해당됩니다.  

     

    (6) Palette = Oranges 색 설정 (pallet colour setting) : scale_fill_brewer()

     

    > # Palette = Oranges 색 설정 (palette colour setting) : scale_fill_brewer()
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway, fill=Cylinders)) +
    +   geom_point(colour="grey", shape=21, size=6) +
    +   scale_fill_brewer(palette="Oranges") # Oranges

     

     

     

     

     

     

    (7) Palette = Reds 색 설정 (pallet colour setting) : scale_fill_brewer()

     

    > # Palette = Reds 색 설정 (palette colour setting) : scale_fill_brewer()
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway, fill=Cylinders)) +
    +   geom_point(colour="grey", shape=21, size=6) +
    +   scale_fill_brewer(palette="Reds") # Reds

     

     

     

     

     

    (8) Palette = Blues 색 설정 (pallet colour setting) : scale_fill_brewer()

     

    > # Palette = Blues 색 설정 (palette colour setting) : scale_fill_brewer()
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway, fill=Cylinders)) +
    +   geom_point(colour="grey", shape=21, size=6) +
    +   scale_fill_brewer(palette="Blues") # Blues

     

     

     

     

    많은 도움 되었기를 바랍니다.

     

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

     

     

    Posted by R Friend R_Friend

    댓글을 달아 주세요

    ggplot2 그래프를 그렸을 때 x축이나 y축의 디폴트 값을 사용해도 무리가 없는 경우가 많기는 합니다만, 

     

    분석가가 x축이나 y축을 좀더 사용하는 목적에 맞게 설정을 조정하고 싶을 때가 있습니다. 

     

    이때 사용할 수 있는 ggplot2의 함수 3가지를 알아보도록 하겠습니다. 

     

    (1) 1:1 의 비율로 x축과 y축 설정

     : coord_fixed()

     

    (2) 일정한 간격으로 x축, y축 설정

     : scale_x_continuous(breaks=seq())

     

    (3) 분석가 마음대로 x축, y축 설정

     : scale_x_continuous(breaks=c())

     

     

    예제로 사용할 데이터는 MASS 패키지에 내장되어 있는 Cars93 데이터 프레임의 도시연비(MPG.city), 고속도로연비(MPG.highway)가 되겠습니다.  scale이 연비로서 서로 같은 변수를 선택하였으며, 산점도를 그려보면서 x축, y축 설정을 바꿔보도록 하겠습니다.

     

    > library(MASS)
    > str(Cars93)
    'data.frame':	93 obs. of  27 variables:
     $ Manufacturer      : Factor w/ 32 levels "Acura","Audi",..: 1 1 2 2 3 4 4 4 4 5 ...
     $ Model             : Factor w/ 93 levels "100","190E","240",..: 49 56 9 1 6 24 54 74 73 35 ...
     $ Type              : Factor w/ 6 levels "Compact","Large",..: 4 3 1 3 3 3 2 2 3 2 ...
     $ Min.Price         : num  12.9 29.2 25.9 30.8 23.7 14.2 19.9 22.6 26.3 33 ...
     $ Price             : num  15.9 33.9 29.1 37.7 30 15.7 20.8 23.7 26.3 34.7 ...
     $ Max.Price         : num  18.8 38.7 32.3 44.6 36.2 17.3 21.7 24.9 26.3 36.3 ...
     $ MPG.city          : int  25 18 20 19 22 22 19 16 19 16 ...
     $ MPG.highway       : int  31 25 26 26 30 31 28 25 27 25 ...
     $ AirBags           : Factor w/ 3 levels "Driver & Passenger",..: 3 1 2 1 2 2 2 2 2 2 ...
     $ DriveTrain        : Factor w/ 3 levels "4WD","Front",..: 2 2 2 2 3 2 2 3 2 2 ...
     $ Cylinders         : Factor w/ 6 levels "3","4","5","6",..: 2 4 4 4 2 2 4 4 4 5 ...
     $ EngineSize        : num  1.8 3.2 2.8 2.8 3.5 2.2 3.8 5.7 3.8 4.9 ...
     $ Horsepower        : int  140 200 172 172 208 110 170 180 170 200 ...
     $ RPM               : int  6300 5500 5500 5500 5700 5200 4800 4000 4800 4100 ...
     $ Rev.per.mile      : int  2890 2335 2280 2535 2545 2565 1570 1320 1690 1510 ...
     $ Man.trans.avail   : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 1 1 1 1 1 ...
     $ Fuel.tank.capacity: num  13.2 18 16.9 21.1 21.1 16.4 18 23 18.8 18 ...
     $ Passengers        : int  5 5 5 6 4 6 6 6 5 6 ...
     $ Length            : int  177 195 180 193 186 189 200 216 198 206 ...
     $ Wheelbase         : int  102 115 102 106 109 105 111 116 108 114 ...
     $ Width             : int  68 71 67 70 69 69 74 78 73 73 ...
     $ Turn.circle       : int  37 38 37 37 39 41 42 45 41 43 ...
     $ Rear.seat.room    : num  26.5 30 28 31 27 28 30.5 30.5 26.5 35 ...
     $ Luggage.room      : int  11 15 14 17 13 16 17 21 14 18 ...
     $ Weight            : int  2705 3560 3375 3405 3640 2880 3470 4105 3495 3620 ...
     $ Origin            : Factor w/ 2 levels "USA","non-USA": 2 2 2 2 2 1 1 1 1 1 ...
     $ Make              : Factor w/ 93 levels "Acura Integra",..: 1 2 4 3 5 6 7 9 8 10 ... 

     

     

     

    ggplot2는 신규 설치 및 호출이 필요한 패키지이므로 아래와 같은 사전 절차가 필요합니다.

     

    > # ggplot2 설치 및 호출

    > install.packages("ggplot2") > library(ggplot2) 

     

    순서대로 하나씩 살펴보겠습니다.  함수 옵션을 바꿔줌에 따라서 x축, y축 결과가 어떻게 바뀌는지 살펴보시고, 필요로 하는 함수 옵션을 선택해서 사용하시면 되겠습니다.

     

    (0) Default setting

     

    > # default setting of x and y axis
    > ggplot(Cars93, aes(x=MPG.city, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black", size=3) + 
    +   ggtitle("default setting of x and y axis") 
     

     

     

     

     

    (1) 1:1 의 비율로 x축과 y축 설정 : coord_fixed()

     

    > # 1:1 proportion of x and y axis : coord_fixed()
    > ggplot(Cars93, aes(x=MPG.city, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black", size=3) + 
    +   coord_fixed() +
    +   ggtitle("1:1 proportion of x and y axis : coord_fixed()")

     

     

     

     

     

     

    (2) 일정한 간격으로 x축과 y축 설정 : scale_x_continuous(breaks=seq())

     

    > # manual setting with fixed interval of x and y axis : scale_x_continuous(breaks=seq())
    > ggplot(Cars93, aes(x=MPG.city, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black", size=3) + 
    +   coord_fixed() +
    +   scale_x_continuous(breaks=seq(0, 80, 5)) + 
    +   scale_y_continuous(breaks=seq(0, 80, 5)) + 
    +   ggtitle("manual setting with fixed interval of x and y axis : scale_x_continuous(breaks=seq())")

     

     

     

     

     

     

     

    (3) 분석가 마음대로 x축과 y축 설정 : scale_x_continuous(breaks=c())

     

    > # manual setting of x and y axis : scale_x_continuous(breaks=c())
    > ggplot(Cars93, aes(x=MPG.city, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black", size=3) + 
    +   coord_fixed() +
    +   scale_x_continuous(breaks=c(10, 15, 20, 25, 30, 40)) + 
    +   scale_y_continuous(breaks=c(20, 25, 30, 40, 50)) + 
    +   ggtitle("manual setting of x and y axis : scale_x_continuous(breaks=c())")

     

     

     

     

    함수 옵션을 바꿔줌에 따라서 x축, y축 결과가 어떻게 바뀌는지 살펴보시고, 필요로 하는 함수 옵션을 선택해서 사용하시면 되겠습니다.

     

    많은 도움 되었기를 바랍니다.

     

     

    Posted by R Friend R_Friend

    댓글을 달아 주세요

    1. 2018.09.13 18:27  댓글주소  수정/삭제  댓글쓰기

      비밀댓글입니다

    2. R Friend R_Friend 2018.09.13 18:47 신고  댓글주소  수정/삭제  댓글쓰기

      (1) 데이터셋을 하나의 데이터프레임으로 합친 후에
      (이때 40개 파일을 구분할 수 있는 요인형(factor) 칼럼이 있어야 함)

      (2) ggplot2의 gacet_grid() 함수를 이용하면 될거 같습니다.
      (참고: rfriend.tistory.com/85 )

    3. 2018.12.26 09:58  댓글주소  수정/삭제  댓글쓰기

      비밀댓글입니다

      • R Friend R_Friend 2018.12.26 13:35 신고  댓글주소  수정/삭제

        안녕하세요 hmmoon 님, url 남겨주신 곳에 가서 확인해보니 산점도인데 그룹에 따라서 색깔을 달리하는 그래프를 원하시는 것 같습니다.

        http://rfriend.tistory.com/72
        포스팅에 가셔서

        > # Scatter Plot by Type, using different Colours
        > ggplot(data=Cars93, aes(x=Weight, y=MPG.highway, colour=Type)) +
        + geom_point(shape=19, size=3) +
        + ggtitle("Scatter Plot by Type, using different Colours")

        코드를 참고하시면 될 듯 합니다.
        해보시고 잘 안되면 다시 한번 댓글 남겨주시구요.

        감사합니다.

    그룹(집단, 요인) 간의 데이터 분포 형태, 변화 추이 등을 비교 분석하기에 유용한 방법으로 비교하려는 축을 기준으로 면을 분할하여 그래프를 그룹 간 비교하는 방법이 있습니다.

     

    Lattice 패키지에서는 Trellis 를 사용하는데요, ggplot2 패키지에서는 facet_grid() 함수facet_wrap() 함수를 사용하여 면 분할을 구현할 수 있습니다.

     

    Base Graphics 패키지에서는 par() 함수를 사용해서 면 분할을 지정해줄 수 있습니다만, x축과 y축의 scale이 들쭉날쭉해서 직접적으로 서로 비교하기가 곤란하거나, y축의 min, max 값이 그룹 간 숫자를 모두 감안해서 자동 설정되는 것이 아니다보니 분석가가 미리 y축 값의 범위를 계산해보고, 혹은 그려보고 나서 y축 값을 세팅해줘야 하므로 lattice나 ggplot2 대비 불편합니다.  따라서 집단간 비교를 위한 면 분할이 필요한 경우 ggplot2나 lattice 패키지를 권합니다.

     

    MASS 패키지 내 무게(Weight), 고속도로연비(MPG.highway), 차종(Type, 범주형), 생산국가(Origin, 범주형) 의 4개 변수를 사용해서, x축에 무게(Weight), y축에 고속도로연비(MPG.highway), 그리고 면 분할의 기준으로 범주형 변수인 차종(Type)과 생산국가(Origin) 변수를 사용하겠습니다.

     

    facet_grid()를 먼저 예제를 보이고, 그 후에 facet_wrap()의 예제를 들겠습니다.  두 함수가 비슷하면서도 조금 다릅니다.  분석가가 필요로 하는 아웃풋 이미지에 맞게 골라서 사용하면 되겠습니다.

     

     

    (1) facet_grid()

     

    > # facet_grid()
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black") +
    +   facet_grid(Type ~ .)
     

     


     

    > ggplot(Cars93, aes(x=Weight, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black") +
    +   facet_grid(. ~ Type)

     

     

     

     


     

    > ggplot(Cars93, aes(x=Weight, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black") +
    +   facet_grid(Origin ~ Type)

     

     

     

     

     

     

     

    (2) facet_wrap()

     

    facet_wrap()는 ncol 또는 nrow 로 행 또는 열의 개수를 분석가가 지정할 수 있어서 좋은 점이 있습니다.

     

    > # facet_wrap()
    > ggplot(Cars93, aes(x=Weight, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black") +
    +   facet_wrap( ~ Type, ncol=3)

     

     

     


     

    > ggplot(Cars93, aes(x=Weight, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black") +
    +   facet_wrap(Origin ~ Type, ncol=3)

     

     

     


     

    > ggplot(Cars93, aes(x=Weight, y=MPG.highway)) +
    +   geom_point(shape=21, colour="black") +
    +   facet_wrap(Origin ~ Type, ncol=2)

     

     

     

     

    많은 도움 되었기를 바랍니다.

     

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

     

     

    Posted by R Friend R_Friend

    댓글을 달아 주세요

    1. 로리너 2017.08.11 16:07 신고  댓글주소  수정/삭제  댓글쓰기

      안녕하세요 포스팅 잘 보고 있습니다.
      질문드릴 것이 하나 있어서 댓글 남겨봅니다..

      몇 가지 요인에 의하여 변동하는 결과값 평균을 비교하기 위해 이러한 모양새로 그래프를 그리고 싶은데요, 이 포스팅과 같은 패키지, 기능을 이용할 수 있나요?

      예를 들어 온도와 산성도, 지속시간을 달리하여 얻어낸 결과값들이 셋 중 어떤 요인에 의하여 더 크게 변화하는지를 시각화하고 싶습니다

      따라해보려 했는데 x축 설정에 애를 먹더군요

      • R Friend R_Friend 2017.08.11 17:43 신고  댓글주소  수정/삭제

        안녕하세요, 로리러님.

        풀려고하는 문제가 정확히 무엇인지 몰라서 답변드리기가 좀 애매한데요, 혹시 이원분산분석으로 풀수 있는 문제이면 아래 포스팅 참고하시기 바랍니다. 중간에 그래프도 포함되어 있습니다.

        http://rfriend.tistory.com/136
        ----------------------------------------------

        그리고 다변량 시각화 하는 필요가 있으시면 블로그의 [다변량 시각화] 구분이 제목에 붙어있는 포스팅도 참고해보시면 좋겠습니다.

        가령, (각 변수 sacle 표준화 후)
        - 평행좌표그림
        - 클리브랜드 점 그래프
        - 3D 산점도

        등을 고려해볼 수 있을거 같습니다.

        -----------------------------------------------

        여러개 변수들의 성대적 (Y값에 대한) 중요도를 시각화 하려면 Random Forest 의 "Feature(Variable) Importance" 도 대안이 될 수있을거 같습니다

    2. 로리너 2017.08.11 17:47 신고  댓글주소  수정/삭제  댓글쓰기

      답변 감사드립니다.

      역시 전달이 힘드네요 ㅎㅎ;

      말씀하신 부분 충분히 알아보겠습니다. 좋은 주말 되십시오

    이전 포스팅에서 x축과 y축의 값에 따라 산점도 그리는 방법을 알아보았다면, 이번 포스팅에서는 여기에 더해서 z라는 제 3의 변수에 비례해서 점의 크기를 변화시켜서 그린 그래프가 버블 그래프 (Bubble Chart) 입니다.  산점도가 2차원의 그래프(단, 색깔이나 모양 조건을 추가하면 3차원 정보 제공 가능)라면, 버블 그래프 (Bubble Chart)는 3차원의 그래프가 되어 지면에 보다 많은 정보량을 제공할 수 있는 장점이 있습니다. 

     

    ggplot2에서는 산점도, 점 그래프를 그리는 geom_point() 함수와 함께 scale_size_area() 함수를 같이 사용하면 버블 그래프 (Bubble Chart)를 그릴 수가 있습니다.

     

    MASS 패키지의 Cars93 데이터 프레임 내에 차 모델명(Model), 차종(Type), 무게(Weight), 고속도로연비(MPG.highway), 가격(Price)의 5개 변수를 사용하여 버블 그래프를 그려보겠습니다.  데이터가 너무 많으면 버블 그래프를 그릴 때 겹쳐 보여서 보기 싫으므로 차종(Type)에서 "compact"와 "large"의 두 종만 선별해서 예를 들어보겠습니다.

     

    > library(MASS)
    > str(Cars93)
    'data.frame':	93 obs. of  27 variables:
     $ Manufacturer      : Factor w/ 32 levels "Acura","Audi",..: 1 1 2 2 3 4 4 4 4 5 ...
     $ Model             : Factor w/ 93 levels "100","190E","240",..: 49 56 9 1 6 24 54 74 73 35 ...
     $ Type              : Factor w/ 6 levels "Compact","Large",..: 4 3 1 3 3 3 2 2 3 2 ...
     $ Min.Price         : num  12.9 29.2 25.9 30.8 23.7 14.2 19.9 22.6 26.3 33 ...
     $ Price             : num  15.9 33.9 29.1 37.7 30 15.7 20.8 23.7 26.3 34.7 ...
     $ Max.Price         : num  18.8 38.7 32.3 44.6 36.2 17.3 21.7 24.9 26.3 36.3 ...
     $ MPG.city          : int  25 18 20 19 22 22 19 16 19 16 ...
     $ MPG.highway       : int  31 25 26 26 30 31 28 25 27 25 ...
     $ AirBags           : Factor w/ 3 levels "Driver & Passenger",..: 3 1 2 1 2 2 2 2 2 2 ...
     $ DriveTrain        : Factor w/ 3 levels "4WD","Front",..: 2 2 2 2 3 2 2 3 2 2 ...
     $ Cylinders         : Factor w/ 6 levels "3","4","5","6",..: 2 4 4 4 2 2 4 4 4 5 ...
     $ EngineSize        : num  1.8 3.2 2.8 2.8 3.5 2.2 3.8 5.7 3.8 4.9 ...
     $ Horsepower        : int  140 200 172 172 208 110 170 180 170 200 ...
     $ RPM               : int  6300 5500 5500 5500 5700 5200 4800 4000 4800 4100 ...
     $ Rev.per.mile      : int  2890 2335 2280 2535 2545 2565 1570 1320 1690 1510 ...
     $ Man.trans.avail   : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 1 1 1 1 1 ...
     $ Fuel.tank.capacity: num  13.2 18 16.9 21.1 21.1 16.4 18 23 18.8 18 ...
     $ Passengers        : int  5 5 5 6 4 6 6 6 5 6 ...
     $ Length            : int  177 195 180 193 186 189 200 216 198 206 ...
     $ Wheelbase         : int  102 115 102 106 109 105 111 116 108 114 ...
     $ Width             : int  68 71 67 70 69 69 74 78 73 73 ...
     $ Turn.circle       : int  37 38 37 37 39 41 42 45 41 43 ...
     $ Rear.seat.room    : num  26.5 30 28 31 27 28 30.5 30.5 26.5 35 ...
     $ Luggage.room      : int  11 15 14 17 13 16 17 21 14 18 ...
     $ Weight            : int  2705 3560 3375 3405 3640 2880 3470 4105 3495 3620 ...
     $ Origin            : Factor w/ 2 levels "USA","non-USA": 2 2 2 2 2 1 1 1 1 1 ...
     $ Make              : Factor w/ 93 levels "Acura Integra",..: 1 2 4 3 5 6 7 9 8 10 ...
    
     
    > levels(Cars93$Type)
    [1] "Compact" "Large"   "Midsize" "Small"   "Sporty"  "Van" 
     
     

    > table(Cars93$Type) Compact Large Midsize Small Sporty Van 16 11 22 21 14 9

     

     

    > # dataset selection

    > Cars93_sample <- subset(Cars93, 
    +                         select = c("Model", "Type", "Weight", "MPG.highway", "Price"), 
    +                         subset = (Type %in% c("Compact", "Large")))
    > Cars93_sample
                Model    Type Weight MPG.highway Price
    3              90 Compact   3375          26  29.1
    7         LeSabre   Large   3470          28  20.8
    8      Roadmaster   Large   4105          25  23.7
    10        DeVille   Large   3620          25  34.7
    12       Cavalier Compact   2490          36  13.4
    13        Corsica Compact   2785          34  11.4
    18        Caprice   Large   3910          26  18.8
    20       Concorde   Large   3515          28  18.4
    21        LeBaron Compact   3085          28  15.8
    22       Imperial   Large   3570          26  29.5
    25         Spirit Compact   2970          27  13.3
    30         Vision   Large   3490          28  19.3
    33          Tempo Compact   2690          27  11.3
    38 Crown_Victoria   Large   3950          26  20.9
    43         Accord Compact   3040          31  17.5
    52       Town_Car   Large   4055          26  36.1
    55            626 Compact   2970          34  16.5
    58           190E Compact   2920          29  31.9
    65         Altima Compact   3050          30  15.7
    68        Achieva Compact   2910          31  13.5
    71   Eighty-Eight   Large   3470          28  20.7
    74        Sunbird Compact   2575          31  11.1
    77     Bonneville   Large   3495          28  24.4
    78            900 Compact   2775          26  28.7
    82         Legacy Compact   3085          30  19.5
    90         Passat Compact   2985          30  20.0
    92            240 Compact   2985          28  22.7

     

     

    ggplot2의 geom_point()와 scale_size_area() 함수를 사용하여 버블 그래프 (bubble chart)를 그려보겠습니다.  ggplot2는 별도의 설치와 호출이 필요한 패키지이므로 아래와 같이 install.packages()와 library()로 설치 및 호출을 먼저 해야 합니다.

     

    > install.packages("ggplot2")
    Installing package into ‘C:/Users/user/Documents/R/win-library/3.2’
    (as ‘lib’ is unspecified)
    trying URL 'http://cran.rstudio.com/bin/windows/contrib/3.2/ggplot2_1.0.1.zip'
    Content type 'application/zip' length 2676272 bytes (2.6 MB)
    downloaded 2.6 MB
    
    package ‘ggplot2’ successfully unpacked and MD5 sums checked
    
    The downloaded binary packages are in
    	C:\Users\user\AppData\Local\Temp\RtmpKeoxEa\downloaded_packages
    > library(ggplot2) 

     

     

     

    x축에는 무게(Weight)를, y축에는 고속도로연비(MPG.highway)를, 원의 크기는 가격(Price)를 설정하였습니다.  그리고 겹치는 부분이 있어서 alpha=0.5 로 해서 반투명하게 하였습니다. scale_size_area 에서 원의 크기의 최대값(max)을 15개 한정을 지었으며, geom_text() 함수를 활용해 vjust=1로 해서 x축 값에 align되고 y값은 MPG.highway값에 살짝 조정을 가해서 label로는 모델명(Model) 변수값을 가져다가 라벨링을 하였습니다.

     

    > # Bubble chart with scale_size_area and label
    > ggplot(Cars93_sample, aes(x=Weight, y=MPG.highway)) + 
    +   geom_point(aes(size=Price), shape=21, colour="grey90", fill="yellow", , alpha=0.5) +
    +   scale_size_area(max_size = 15) + # 범례 없애려면 guide=FALSE
    +   geom_text(aes(y=as.numeric(MPG.highway)-sqrt(Price)/10, label=Model), 
    +             vjust=1, colour="grey40", size=3) + 
    +   ggtitle("Bubble chart with scale_size_area and label") 
     
     

     

     

    많은 도움이 되었기를 바랍니다.

     

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

     

      

    Posted by R Friend R_Friend

    댓글을 달아 주세요

    1. 2016.08.05 16:19  댓글주소  수정/삭제  댓글쓰기

      비밀댓글입니다

    2. 조정호 2017.07.04 19:31  댓글주소  수정/삭제  댓글쓰기

      Rfriend님 질문이 또 생겼네요ㅎㅎ

      ggplot(Cars93_sample, aes(x=Weight, y=MPG.highway)) +
      geom_point(aes(size=Price), shape=21, colour="grey90", fill="yellow", alpha=0.5)+
      scale_size_area(max_size=15)+
      geom_text(aes(y=as.numeric(MPG.highway)-sqrt(Price)/10, label=Model),
      vjust=1, colour="grey40", size=3) +
      ggtitle("Bubble chart")

      이코드에서 geom_text의 위치가 왜 as.numeric(MPG.highway)-sqrt(Price)/10 이렇게 되는지 설명
      부탁드립니다.

      • R Friend R_Friend 2017.07.04 21:11 신고  댓글주소  수정/삭제

        안녕하세요 조정호님.

        문의하신 geom_text 위치를
        as.numeric(MPG.highway)-sqrt(Price)/10
        했던 이유는 Y 축의 값으로 MPG.highway 만 할 경우 서로 겹치는 것들이 있어서 'sqrt(Price)/10'를 추가하여 빼줌으로써 그래프 Y 축의 LABEL이 서로 어긋나게 하려고 했던거구요, 왜 'sqrt(Price)/10' 이냐 하면 그냥 적당한 위치를 찾다가 이렇게도 해보고 저렇게도 해보다가 trial & error 몇 번 해보고 그냥 이렇게 한것입니다. 무슨 학문적인 배경이나 이론... 이런 것은 없습니다. ^^; 본문의 그래프를 다시 유심히보니 Y축으로 중첩되는 것을 그리 잘 해결하지는 못해보이네요. ^^;;;

        다른 방식으로 더 좋은 방법, 수식이 있을 텐데요, 한번 아이디어를 내보시는 것도 재미있을 듯 합니다.

    산점도는 두 변수간의 관계를 파악하는데 굉장히 유용한 시각화 방법입니다.  그리고 산점도 행렬은 다수의 변수들 간의 관계를 한눈에 파악하는데 유용한 시각화 방법이구요.

     

    이전 포스팅에서

    - ggplot2의 geom_point() 함수를 이용한 한개 변수의 산점도 그리기

    - corrplot 패키지를 이용한 상관계수 행렬 그림 그리기

    를 소개했었습니다.

     

    ggplot2로 두 변수만 가지고 산점도는 유연하게 그릴 수 있는데요, 3개 이상의 변수를 가지고 산점도 행렬을 그리기는 매우 힘이 듭니다. (프로그래밍을 해야 합니다)  따라서 산점도 행렬은 plot() 함수를 써서 한방에 그리는 것이 제일 편하구요,

     

    이번 포스팅에서는 Base Graphics 패키지 내에 pairs() 함수를 이용해서 산점도 행렬에 몇가지 사용자 정의 함수를 추가하여 히스토그램도 집어 넣고 상관계수 숫자도 포함시키는 방법을 소개하겠습니다.  산점도 행렬에 많은 추가 정보를 담을 수 있어서 매우 보기에 좋고 유용합니다. 사용자 정의 함수는 pairs() 도움말(help)을 참조하였습니다.

     

     

    예제로 사용한 데이터는 뉴욕의 1973년도 공기의 질을 측정한 airquality 데이터셋의 Ozone, Solar.R, Wind, Temp 4개의 변수가 되겠습니다.

     

    > str(airquality)
    'data.frame':	153 obs. of  6 variables:
     $ Ozone  : int  41 36 12 18 NA 28 23 19 8 NA ...
     $ Solar.R: int  190 118 149 313 NA NA 299 99 19 194 ...
     $ Wind   : num  7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
     $ Temp   : int  67 72 74 62 56 66 65 59 61 69 ...
     $ Month  : int  5 5 5 5 5 5 5 5 5 5 ...
     $ Day    : int  1 2 3 4 5 6 7 8 9 10 ...
    > 

    > # 1~4번째 변수만 선택

    > airquality_1 <- airquality[,c(1:4)]
    > str(airquality_1)
    'data.frame':	153 obs. of  4 variables:
     $ Ozone  : int  41 36 12 18 NA 28 23 19 8 NA ...
     $ Solar.R: int  190 118 149 313 NA NA 299 99 19 194 ...
     $ Wind   : num  7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
     $ Temp   : int  67 72 74 62 56 66 65 59 61 69 ... 

     

     

    결측값이 있으면 상관계수를 구할 때 NA 값이 나오므로, 결측값 여부 확인하고 결측값이 있는 행은 삭제한 후에 산점도 행렬을 그려보겠습니다.

     

    > # 결측값 개수 확인
    > sum(is.na(airquality_1$Ozone)) # 37
    [1] 37
    > sum(is.na(airquality_1$Solar.R)) # 7
    [1] 7
    > sum(is.na(airquality_1$Wind)) # 0
    [1] 0
    > sum(is.na(airquality_1$Temp)) # 0
    [1] 0
    > 
    > # 결측값 있는 상태에서 상관계수 계산했을 때
    > cor(airquality_1)
            Ozone Solar.R       Wind       Temp
    Ozone       1      NA         NA         NA
    Solar.R    NA       1         NA         NA
    Wind       NA      NA  1.0000000 -0.4579879
    Temp       NA      NA -0.4579879  1.0000000
    > 
    > # 결측값 있는 행 전체 삭제
    > airquality_2 <- na.omit(airquality_1)
    > str(airquality_2)
    'data.frame':	111 obs. of  4 variables:
     $ Ozone  : int  41 36 12 18 23 19 8 16 11 14 ...
     $ Solar.R: int  190 118 149 313 299 99 19 256 290 274 ...
     $ Wind   : num  7.4 8 12.6 11.5 8.6 13.8 20.1 9.7 9.2 10.9 ...
     $ Temp   : int  67 72 74 62 65 59 61 69 66 68 ...
     - attr(*, "na.action")=Class 'omit'  Named int [1:42] 5 6 10 11 25 26 27 32 33 34 ...
      .. ..- attr(*, "names")= chr [1:42] "5" "6" "10" "11" ...
    > sum(is.na(airquality_2$Ozone)) # 0
    [1] 0
    > sum(is.na(airquality_2$Solar.R)) # 0
    [1] 0 

     

     

     

    산점도 행렬의 대각선에 히스토그램을 추가하는 사용자 정의 함수입니다.  pairs() 도움말(help)에 나와있는 사용자 정의함수 그대로 가져왔습니다.  아래 사용자 정의 함수를 카피해서 사용하시기 바랍니다.

     

    ## put histograms on the diagonal
    panel.hist <- function(x, ...)
    {
      usr <- par("usr"); on.exit(par(usr))
      par(usr = c(usr[1:2], 0, 1.5) )
      h <- hist(x, plot = FALSE)
      breaks <- h$breaks; nB <- length(breaks)
      y <- h$counts; y <- y/max(y)
      rect(breaks[-nB], 0, breaks[-1], y, col = "cyan", ...)

     

    # source: help(pairs)

     

     

     

    다음으로 산점도 행렬의 위쪽에 상관계수 숫자를 집어넣는 사용자 정의 함수입니다.  이 또한 pairs() 도움말(help)에 나와있는 사용자 정의함수 그대로 가져왔습니다.  아래 사용자 정의 함수를 카피해서 사용하시기 바랍니다.

     

    ## put (absolute) correlations on the upper panels,
    ## with size proportional to the correlations.
    panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor, ...)
    {
      usr <- par("usr"); on.exit(par(usr))
      par(usr = c(0, 1, 0, 1))
      r <- abs(cor(x, y))
      txt <- format(c(r, 0.123456789), digits = digits)[1]
      txt <- paste0(prefix, txt)
      if(missing(cex.cor)) cex.cor <- 0.8/strwidth(txt)
      text(0.5, 0.5, txt, cex = cex.cor * r)

     

    # source : help(pairs)

     

     

     

    다음으로 산점도에 선형 회귀선을 추가하는 사용자 정의 함수입니다.  이는 R Graphics Cookbook (원스턴 챙 지음, 이제원 옮김)을 참조하였습니다.  아래 사용자 정의 함수를 카피해서 사용하시기 바랍니다.

     

    ## put linear regression line on the scatter plot
    panel.lm <- function(x, y, col=par("col"), bg=NA, pch=par("pch"),
                         cex=1, col.smooth="black", ...) {
      points(x, y, pch=pch, col=col, bg=bg, cex=cex)
      abline(stats::lm(y~x), col=col.smooth, ...)

     

     

     

    이제 준비가 다 되었습니다.  airquality의 4개 변수 간의 산점도 행렬, 상관계수 숫자, 히스토그램을 하나의 도표로 나타내보겠습니다.

     

    > ## 산점도 행렬(scatter-plot matrix), 상관계수(correlation), 히스토그램(histogram) > pairs(airquality_2, + lower.panel = panel.lm, # 아래쪽 산점도에 선형 직선 추가 + upper.panel = panel.cor, # 위쪽에는 상관계수 숫자 (상관계수에 크기 비례) + diag.panel = panel.hist, # 대각선에는 히스토그램 + pch="*", # 점 모양은 * 로 + main = "scatter-plot matrix, correlation coef., histogram" + )

     

     

     

     

     

     

    보너스로, pairs() 함수를 사용해서 범주(그룹)별로 점의 색깔을 달리하는 방법도 소개하겠습니다.  이 역시 pairs() 함수 도움말(help)에 있는 R script 를 가져왔습니다.  도움말(help)이 정말 도움이 많이 됩니다. ^^  사용한 데이터는 그 유명한 Iris 데이터가 되겠습니다.

     

    > # 범주(그룹)을 색깔로 구분하여 산점도 행렬 그리기
    > pairs(iris[1:4], main = "Anderson's Iris Data -- 3 species",
    +       pch = 21, bg = c("red", "green3", "blue")[unclass(iris$Species)])

     

     

     * R script source : help(pairs)

     

    많은 도움 되셨기를 바랍니다.

     

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

     

    Posted by R Friend R_Friend

    댓글을 달아 주세요

    다수의 변수간 상관관계를 파악하려고 할 때, 회귀분석에서 종속변수와 독립변수간 선형관계를 파악하거나 독립변수간 다중공선성을 파악하려고 할 때 사용하는 분석 기법이 상관계수 행렬이며, 시각화 방법이 산점도 행렬과 상관계수 행렬 Plot (correlation matrix plot) 입니다.

     

    이전 포스팅에서 ggplot2의 geom_point() 산점도를 다루었으며,

     

    다음 포스팅에서는 Base Graphics 패키지의 pairs() 함수를 사용한 산점도 행렬을 소개하였고,

     

    이번 포스팅에서는 상관계수 행렬 Plot을 중심으로 해서 corrplot 패키지 사용법을 알아보겠습니다. 

     

     

    예제로 사용한 데이터는 뉴욕의 1973년도 공기의 질을 측정한 airquality 데이터셋의 Ozone, Solar.R, Wind, Temp 4개의 변수가 되겠습니다.

     

     

    > str(airquality)
    'data.frame':	153 obs. of  6 variables:
     $ Ozone  : int  41 36 12 18 NA 28 23 19 8 NA ...
     $ Solar.R: int  190 118 149 313 NA NA 299 99 19 194 ...
     $ Wind   : num  7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
     $ Temp   : int  67 72 74 62 56 66 65 59 61 69 ...
     $ Month  : int  5 5 5 5 5 5 5 5 5 5 ...
     $ Day    : int  1 2 3 4 5 6 7 8 9 10 ...
    > 

    > # Month, Day는 빼기

    > airquality_1 <- airquality[,c(1:4)]
    > 
    > str(airquality_1)
    'data.frame':	153 obs. of  4 variables:
     $ Ozone  : int  41 36 12 18 NA 28 23 19 8 NA ...
     $ Solar.R: int  190 118 149 313 NA NA 299 99 19 194 ...
     $ Wind   : num  7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
     $ Temp   : int  67 72 74 62 56 66 65 59 61 69 ...

     

     

     

     

    상관계수 분석을 할 때 결측값이 있으면 NA 값이 나오게 되므로 사전에 결측값 처리하는 것이 필요합니다.  Ozone과 Solar.R이 결측값이 각각 37개, 7개 있다보니 아래처럼 상관계수가 NA가 나왔습니다.

     

    > # 결측값 확인
    > sum(is.na(airquality_1$Ozone)) # 37
    [1] 37
    > sum(is.na(airquality_1$Solar.R)) # 7
    [1] 7
    > sum(is.na(airquality_1$Wind)) # 0
    [1] 0
    > sum(is.na(airquality_1$Temp)) # 0
    [1] 0
    > # 결측값 있는 상태에서 상관계수 계산했을 때
    > cor(airquality_1)
            Ozone Solar.R       Wind       Temp
    Ozone       1      NA         NA         NA
    Solar.R    NA       1         NA         NA
    Wind       NA      NA  1.0000000 -0.4579879
    Temp       NA      NA -0.4579879  1.0000000

     

     

     

     

    na.omit() 함수를 사용하여 결측값이 있는 행 전체를 삭제한 후에 상관계수를 구해보면 아래와 같습니다.  corrplot 패키지의 corrplot() 함수는 상관계수 행렬 데이터셋을 가지고 그래프를 그리므로 아래처럼 결측값을 제거한 후의 데이터셋을 가지고 미리 상관계수 행렬을 계산해두어야 합니다.

     

     

    > # 결측값 있는 행 전체 삭제
    > airquality_2 <- na.omit(airquality_1)
    > str(airquality_2)
    'data.frame':	111 obs. of  4 variables:
     $ Ozone  : int  41 36 12 18 23 19 8 16 11 14 ...
     $ Solar.R: int  190 118 149 313 299 99 19 256 290 274 ...
     $ Wind   : num  7.4 8 12.6 11.5 8.6 13.8 20.1 9.7 9.2 10.9 ...
     $ Temp   : int  67 72 74 62 65 59 61 69 66 68 ...
     - attr(*, "na.action")=Class 'omit'  Named int [1:42] 5 6 10 11 25 26 27 32 33 34 ...
      .. ..- attr(*, "names")= chr [1:42] "5" "6" "10" "11" ...
    > sum(is.na(airquality_2$Ozone)) # 0
    [1] 0
    > sum(is.na(airquality_2$Solar.R)) # 0
    [1] 0
    > # 상관계수 계산
    > airquality_cor <- cor(airquality_2)
    > airquality_cor
                 Ozone    Solar.R       Wind       Temp
    Ozone    1.0000000  0.3483417 -0.6124966  0.6985414
    Solar.R  0.3483417  1.0000000 -0.1271835  0.2940876
    Wind    -0.6124966 -0.1271835  1.0000000 -0.4971897
    Temp     0.6985414  0.2940876 -0.4971897  1.0000000
     

     

     

     

    corrplot 패키지는 별도의 설치 및 호출이 필요한 패키지이므로 아래의 절차를 거칩니다.

     

    > install.packages("corrplot")
    Installing package into ‘C:/Users/user/Documents/R/win-library/3.2’
    (as ‘lib’ is unspecified)
    trying URL 'http://cran.rstudio.com/bin/windows/contrib/3.2/corrplot_0.73.zip'
    Content type 'application/zip' length 2680505 bytes (2.6 MB)
    downloaded 2.6 MB
    
    package ‘corrplot’ successfully unpacked and MD5 sums checked
    
    The downloaded binary packages are in
    	C:\Users\user\AppData\Local\Temp\Rtmpk1gkRL\downloaded_packages
    > library(corrplot) 

     

     

     

    산점도 행렬 그림 (scatter matrix plot)을 복습해보자면 아래와 같습니다.

     

    > # scatter plot matrix
    > plot(airquality_2)

     

     

     

     

     

    correlation plot의 method 에는 method = c("circle", "square", "ellipse", "number", "shade", "color", "pie") 등이 있으며, method별로 하나씩 예를 들어보겠습니다.

     

     

    > corrplot(airquality_cor, method="circle")
     

     

     

    > corrplot(airquality_cor, method="square")

     

     

     

      

    > corrplot(airquality_cor, method="ellipse")

     

     

     

     

    > corrplot(airquality_cor, method="number")

     

     

     

     

    > corrplot(airquality_cor, method="shade")

     

     

     

     

    > corrplot(airquality_cor, method="color")

     

     

     

     

    > corrplot(airquality_cor, method="pie")

     

     

     

     

    마지막으로 mehtod="shade", 상관관계 방향성 제시, 대각선 값 미제시, 상관계수 숫지 검정색으로 해서 추가해서 corrplot을 그려보겠습니다.  order 는 FPC(First Principle Component), hclust(hierarchical clustering), AOE(Angular Order of Engenvectors) 등이 있으며, 정렬 기준을 지정해주면 같은 색깔 끼리 뭉쳐서 보일 수 있도록 정렬을 시켜줘서 보기에, 해석하기에 더 좋게 보여줍니다.

     

    > # corrplot
    > corrplot(airquality_cor, 
    +          method="shade", # 색 입힌 사각형
    +          addshade="all", # 상관관계 방향선 제시
    +          # shade.col=NA, # 상관관계 방향선 미제시
    +          tl.col="red", # 라벨 색 지정
    +          tl.srt=30, # 위쪽 라벨 회전 각도
    +          diag=FALSE, # 대각선 값 미제시
    +          addCoef.col="black", # 상관계수 숫자 색
    +          order="FPC" # "FPC": First Principle Component
    +                      # "hclust" : hierarchical clustering
    +                      # "AOE" : Angular Order of Eigenvectors
    +          )

     

     

     

     

    많은 도움이 되었기를 바랍니다.

     

    -----------

     

    (참고) pairs() 함수를 활용한 상관계수 행렬 그리기 ☞ http://rfriend.tistory.com/83

     

    -----------

     

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

     

    Posted by R Friend R_Friend

    댓글을 달아 주세요

    1. 스윗쥬스 2016.08.04 17:06 신고  댓글주소  수정/삭제  댓글쓰기

      order Option은 3가지가 있습니다.
      직접 테스트를 했는데도, 어떤 기준으로 정렬하는지 파악이 잘 안되네요.
      각 기준이 어떻게 정렬하는지 알려주실 수 있으실까요..?

      1.FPC(First Principle Component)
      2.hclust(hierarchical clustering)
      3.AOE(Angular Order of Engenvectors)

      • R Friend R_Friend 2016.08.04 23:00 신고  댓글주소  수정/삭제

        스윗쥬스님,

        order option별로 설명을 드리자면,

        1)FPC(First Principle Component)

        주성분분석이 데이터의 분산을 최대로 많이 설명할 수 있는 선형조합을 찾는 것이며, 제1 주성분이 데이터의 정보량을 가장 많이 설명을 합니다. 보통 변수들 간에 상관성이 높을 수록 제1 주성분의 설명력가 높습니다. 이론상으로는 제1 주성분에 대한 변수별 기여도를 가지고 ordering을 하면 서로 상관성이 높은 변수들의 순서대로 정렬이 될겁니다.


        ☞ 주성분분석(PCA) 참고 포스팅 :
        http://rfriend.tistory.com/61


        2)hclust(Hierarchical Clustering) :

        계층적 군집화 방법에는 6가지 세부 알고리즘이 있는데요, 기본 원리는 객체 간 유사성(similarity)을 측정해서 유사한 객체끼리 군집이 하나가 될때까지 반복해서 묶어주는 작업을 합니다. 보통은 Euclidean Distance 를 가지고 유사성(정확히는 비유사성, dissimilarity)를 측정해서 군집화를 해줍니다. 앞서 말씀드린 주성분분석 (혹은 요인분석)은 '변수'에 대해서 '상관성'을 가지고 주성분으로 묶어주는 것이라면, 군집분석은 '객체(관측치)'에 대해서 '유사성'을 가지고 군집으로 묶어주는 것입니다.

        따라서 상관관계분석의 ordering 기준으로 계층적군집분석을 쓴다는게 어떤 매카니즘인지를 저는 정확히 이해를 못하겠습니다. ^^; 죄송합니다.

        보통 군집분석 끝내고 나면 군집별로 특성 파악을 위해 변수들과 cross-tabulation 해가면서 profiling을 하는데요, 각 군집별로 특성을 잘 나타낼 수 있는 변수들이 있다면 그 변수들의 상관성이 높다고 해석할 수도 있을 것 같습니다.

        ☞ 응집형 계층적 군집화 - 단일(최단) 연결법 참고 포스팅 :
        http://rfriend.tistory.com/202


        3) AOE(Angular Order of Eigenvectors) :

        1)번에서 주성분분석을 얘기했었는데요, 주성분 구할 때 성분을 분해하면서 고유값(Eigenvalue)과 고유벡터(Eigenvector)를 사용합니다. 첫번째, 두번째, ... 이 순서대로 고유값이 컸다가 작아지구요, 설명력도 첫번째 고유값, 고유벡터가 제일 크고 점점 작아진다고 생각하시면 됩니다. 1)번의 FPC와 대략 같은 맥락의 order 기준이라고 생각하시면 될거 같습니다.

        ☞ 고유값(eigenvalue), 고유벡터(eigenvector) 참고 포스팅 : http://rfriend.tistory.com/181

      • 스윗쥬스 2016.08.05 16:15 신고  댓글주소  수정/삭제

        답변감사합니다 ~
        덕분에 많이 공부했습니다. ^^

    2. 지나가던학생 2016.11.09 20:26  댓글주소  수정/삭제  댓글쓰기

      저 질문이 있는데... 상관계수 구해서 시각화할때 유의성, 즉 p값은 고려하지 않고, 단순 값만 시각화 된것인가요? 만약 저 매트릭스에서 p값이 유의하지 않게 나온 값은 표시되지 않게 할수 있는 방법은 없을까요

      • R Friend R_Friend 2016.11.10 00:26 신고  댓글주소  수정/삭제

        pairs() 함수와 사용자 정의 함수를 사용하면 (두 변수들 간의) 산점도 행렬 + (한 변수의) 히스토그램 + (두 변수들 간의) 상관계수를 한꺼번에 볼 수 있습니다.

        특히 우측 상단의 상관계수의 절대값 크기에 비례해서 숫자 크기가 달라짐에 따라 상관계수절대값이 큰 값만 눈에 잘 띄며, 별로 관계가 없는 값은 숫자 크기가 매우 작게 나타나는 시각화 효과를 제공합니다.

        아래 링크의 포스팅 참고하세요.

        => http://rfriend.tistory.com/83

    ggplot2로 막대그래프를 그렸는데 데이터가 양수와 음수로 구분이 되는 경우 그래프의 가독성을 높이기 위해서 양수냐, 음수냐에 따라 색상을 다르게 하고 싶을 때가 있습니다.

     

    이번 포스팅에서는 R에 내장되어 있는 airquaility 데이터셋 (뉴욕의 1973년 5월~9월까지의 daily air quality measurements) 에서 5월달 온도(Temp) 만을 가져온 후에, 5월달 daily 온도의 1차 차분 데이터를 만들어서 막대그래프를 그려보도록 하겠습니다.

     

    > str(airquality) 'data.frame': 153 obs. of 6 variables: $ Ozone : int 41 36 12 18 NA 28 23 19 8 NA ... $ Solar.R: int 190 118 149 313 NA NA 299 99 19 194 ... $ Wind : num 7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ... $ Temp : int 67 72 74 62 56 66 65 59 61 69 ... $ Month : int 5 5 5 5 5 5 5 5 5 5 ... $ Day : int 1 2 3 4 5 6 7 8 9 10 ... > sum(is.na(airquality$Temp)) [1] 0

    >

    > # 5월 온도만 선택
    > May <- subset(airquality, select = c(Month, Day, Temp), subset = (Month == "5"))

    >

     

     

    온도의 1차 차분은 diff(변수, lag=차수) 함수를 사용합니다.  아래는 1차 차분을 하였으므로 5월1일은 빼고, 5월2일부터 5월31일까지의 날짜만 가져온 후에, 날짜와 온도 1차 차분한 값을 data frame으로 묶었습니다.  그 후에 ifelse() 함수를 사용해서 온도 1차 차분 값이 0 이상이면 "PLUS", 0 미만이면 "MINUS"라는 구분자 변수를 새로 생성하였습니다. 

     

    > # 온도의 1차 차분
    > May_Temp_Diff <- diff(May$Temp, lag=1)
    > May_Temp_Diff
     [1]   5   2 -12  -6  10  -1  -6   2   8   5  -5  -3   2 -10   6   2  -9  11  -6  -3  14 -12   0  -4   1  -1  10  14  -2
    [30]  -3
     
     

    > # 5월2일 ~ 5월31일 날짜 변수 > May_Day <- May[c(2:31), c("Day")] > May_Day [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 >

     

    > May_Temp_Diff.df <- data.frame(May_Day, May_Temp_Diff) > May_Temp_Diff.df May_Day May_Temp_Diff 1 2 5 2 3 2 3 4 -12 4 5 -6 5 6 10 6 7 -1 7 8 -6 8 9 2 9 10 8 10 11 5 11 12 -5 12 13 -3 13 14 2 14 15 -10 15 16 6 16 17 2 17 18 -9 18 19 11 19 20 -6 20 21 -3 21 22 14 22 23 -12 23 24 0 24 25 -4 25 26 1 26 27 -1 27 28 10 28 29 14 29 30 -2 30 31 -3 >

    > # 온도 차분 plus, minus 여부 구분자 변수 생성

    > attach(May_Temp_Diff.df) > May_Temp_Diff.df$plus_minus <- ifelse(May_Temp_Diff >= 0, "PLUS", "MINUS") > May_Temp_Diff.df May_Day May_Temp_Diff plus_minus 1 2 5 PLUS 2 3 2 PLUS 3 4 -12 MINUS 4 5 -6 MINUS 5 6 10 PLUS 6 7 -1 MINUS 7 8 -6 MINUS 8 9 2 PLUS 9 10 8 PLUS 10 11 5 PLUS 11 12 -5 MINUS 12 13 -3 MINUS 13 14 2 PLUS 14 15 -10 MINUS 15 16 6 PLUS 16 17 2 PLUS 17 18 -9 MINUS 18 19 11 PLUS 19 20 -6 MINUS 20 21 -3 MINUS 21 22 14 PLUS 22 23 -12 MINUS 23 24 0 PLUS 24 25 -4 MINUS 25 26 1 PLUS 26 27 -1 MINUS 27 28 10 PLUS 28 29 14 PLUS 29 30 -2 MINUS 30 31 -3 MINUS 

     
    > detach(May_Temp_Diff.df)

     

     

    ggplot2 패키지는 사용자가 추가로 설치해야 합니다.  intall.packages()함수로 설치하고 library() 함수로 호출해보겠습니다.

     

    > install.packages("ggplot2")
    > library(ggplot2) 

     

     

     

    이제 준비가 다 되었습니다.  1차 차분한 5월달의 온도에 대해서 양수(전날 보다 온도 상승)는 빨간색, 음수(전날보다 온도 하락)는 파란색으로 막대 그래프를 그려보겠습니다.  aes(fill=구분자 변수) 함수를 사용하고, 색깔지정은 scale_fill_manual(values=c(색깔1, 색깔2)) 로 지정해주면 됩니다.

     

    > # 양수는 빨간색, 음수는 파란색으로 막대 색 구분
    > ggplot(data=May_Temp_Diff.df, aes(x=May_Day, y=May_Temp_Diff, fill=plus_minus)) + 
    +   geom_bar(stat="identity", position="identity", colour="white", width=0.2) + # width 막대 폭 좁게
    +   scale_fill_manual(values=c("blue", "red"), guide=FALSE) + # guide=F 범례 생략
    +   ggtitle("1st order differenced Temp of May")

     

     

     

     

     

     

    막대 폭이 너무 가늘어서 보기 싫다면, 막대 폭을 좀더 넓히고 싶다면 geom_bar(width=숫자) 함수를 사용하면 됩니다.

     

    > # width 막대 폭 넓게
    > ggplot(data=May_Temp_Diff.df, aes(x=May_Day, y=May_Temp_Diff, fill=plus_minus)) + 
    +   geom_bar(stat="identity", position="identity", colour="white", width=1) + # width 막대 폭 넓게 
    +   scale_fill_manual(values=c("blue", "red"), guide=FALSE) + # guide=F 범례 생략
    +   ggtitle("1st order differenced Temp of May")

     

     

     

     

     

    다음으로, 위의 그래프에서 보면 ggplot2 가 알아서 x축을 10, 20, 30으로 해서 10일 간격으로 설정해서 그래프를 그렸는데요, 이를 좀더 세분화하고 싶다면 scale_x_continuous(breaks=c(숫자, 숫자...)) 로 지정해주면 됩니다.

     

    > # x축 세분화
    > ggplot(data=May_Temp_Diff.df, aes(x=May_Day, y=May_Temp_Diff, fill=plus_minus)) + 
    +   geom_bar(stat="identity", position="identity", colour="white", width=0.5) + 
    +   scale_fill_manual(values=c("blue", "red"), guide=FALSE) + 
    +   ggtitle("1st order differenced Temp of May") + 
    +   scale_x_continuous(breaks=c(5, 10, 15, 20, 25, 30)) # x축 세분화

     

     

     

     

     

    마지막으로, x축과 y축의 라벨 이름이 위에 보면 변수명이 그래도 들어가 있는데요, 좀더 이해하기 쉽도록 xlab(), ylab() 함수를 추가하여 x축, y축 라벨을 변경해보도록 하겠습니다.

     

    > # modification of x label, y label
    > ggplot(data=May_Temp_Diff.df, aes(x=May_Day, y=May_Temp_Diff, fill=plus_minus)) + 
    +   geom_bar(stat="identity", position="identity", colour="white", width=0.5) + 
    +   scale_fill_manual(values=c("blue", "red"), guide=FALSE) + 
    +   ggtitle("1st order differenced Temp of May") + 
    +   scale_x_continuous(breaks=c(5, 10, 15, 20, 25, 30)) + 
    +   xlab("Day of May, 1973") + 
    +   ylab("Temp difference from previous day")

     

     

     

     

    많은 도움 되었기를 바랍니다.

     

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

     

     

    Posted by R Friend R_Friend

    댓글을 달아 주세요