'for()'에 해당되는 글 1건

  1. 2015.09.05 R 반복 연산 프로그래밍(Loop process programming) : for(), while() (8)

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 도 생각해볼 수 있겠네요.