본문 바로가기

R

R 활용 #2 가능한 순서쌍 ordered pair (x,y) 를 출력해 보자

Motivation: 아래와 같이 여학생으로 구성된 집합과 남학생으로 구성된 집합이 주어질 경우, (여, 남) 방식으로 가능한 순서쌍 ordered pair를 전부 출력해 보자. 

 

여학생의 집합 = {영희, 수진, 미현}

남학생의 집합 = {진수, 경호, 윤호, 명진, 기철} 

 

예: (영희, 진수), (영희, 경호), (영희, 윤호), ... (수진, 명진), ... (미현, 진수), ... (미현, 기철) 

 

사용한 개념: for ... loop, if ... then, 연산자(operator) %/% %%, length, matrix 등 

사용 플랫폼: R Studio

작성일: 2022년 1월 29일 토요일

 

최종결과물: (참고를 위해 파일 첨부도 했다.) 

20210128_matching_dates.R
0.01MB

> print(x)
      [,1]   [,2]  
 [1,] "영희" "진수"
 [2,] "영희" "경호"
 [3,] "영희" "윤호"
 [4,] "영희" "명진"
 [5,] "영희" "기철"
 [6,] "수진" "진수"
 [7,] "수진" "경호"
 [8,] "수진" "윤호"
 [9,] "수진" "명진"
[10,] "수진" "기철"
[11,] "미현" "진수"
[12,] "미현" "경호"
[13,] "미현" "윤호"
[14,] "미현" "명진"
[15,] "미현" "기철"

최종 결과물: (codes)

base1 <- c('영희', '수진', '미현')
base2 <- c('진수', '경호', 
           '윤호', '명진', '기철')

length(base1)*length(base2)

x <- matrix(0, 
            ncol=2, 
            nrow=length(base1)
            *length(base2))

for (i in 1:nrow(x))
{
  if (i %% length(base2) == 0) 
    {l <- length(base2)}
  
  else
    {l <- i %% length(base2)}
  
  x[i,2] <- base2[l]
    
  if (i %% length(base2) == 0) 
    {k <- i %/% length(base2)}
  else 
    {k <- i %/% length(base2) + 1}
  
  x[i,1] <- base1[k]
}

print(x)

 

덧: Tistory 블로그의 기능 중 "코드블럭"을 통해 R 코드를 따로 올릴 수 있는 것을 확인했다. Tistory 개발자님들 + 기획자님들께 감사드린다. 

 

내가 실제로 Trial and error 방식을 통해 코딩을 한 step들을 적는다. 

Step 1: R에서 matrix를 구현해 보자.  일단 쉬운 예제부터. x<- matrix(...) 

Step 2: for ... loop 를 활용하여 matrix 내의 원소 값을 일련의 방식으로 채워보자

Step 3: 남학생 집합을 'base' 라고 명명한다. 남학생 수를 3명으로 가정하고, 남학생 수만큼 원소를 채워넣는다.

Step 4: 본래 문제로 돌아가서, 3명의 여학생과 5명의 남학생으로 구성된 순서쌍을 출력해 보자. 

Step 5: step 4 코드가 기존 여학생들과 남학생들 이름을 대체하여도 작동하는지 확인해 보자

 

 

Step 1: R에서 matrix를 구현해 보자.  일단 쉬운 예제부터. x<- matrix(...) 

x <- matrix(0, ncol=2, nrow=6)

해석: x 라는 개체를 matrix로 지정하는데, matrix 내의 각 원소(element)는 0인 0 matrix이다. Matrix의 column 숫자는 2개, row 숫자는 6개로 지정한다. 

결과물: 

     [,1] [,2]
[1,]    0    0
[2,]    0    0
[3,]    0    0
[4,]    0    0
[5,]    0    0
[6,]    0    0

 

Step 2: for ... loop 를 활용하여 matrix 내의 원소 값을 일련의 방식으로 채워보자

for(i in 1:nrow(x))
  {
    x[i,2] <- i
  }

해석: x matrix의 [i,2] 원소를 일련의 방식 (여기에서는 1,2,3,... 처럼 1씩 증가하는 자연수로 채워보려 한다) 으로 채워보자. i 라는 변수를 지정하여, x matrix의 row 숫자만큼 (6줄로 구성됨) for ... loop 문이 진행된다. x 메트릭스의 [1,2]원소는  1, [2,2] 원소는 2, [3,2] 원소는 3 이런식으로 row 숫자만큼 채워나간다. 

 

결과물: 

> x
     [,1] [,2]
[1,]    0    1
[2,]    0    2
[3,]    0    3
[4,]    0    4
[5,]    0    5
[6,]    0    6

 

 Step 3: 남학생 집합을 'base' 라고 명명하고, 남학생 수를 3명으로 가정하고, 남학생 수만큼 원소를 채워넣는다. 직관적인 편의를 위해 1부터 시작한다. 
base <- c(1,2,3)

임의의 여학생 A가 있다고 가정하고, 이 여학생과 파트너될 남자는 3명이다. 순서쌍도 3개이다: (여학생 A, 남학생 1), (여학생A, 남학생 2), (여학생A, 남학생 3). 마찬가지로 임의의 여학생 B에 대해 파트너가 될 순서쌍도 3개이다. 

1번 열: (A, 1)
2번 열: (A, 2)
3번 열: (A, 3)
4번 열: (B, 1)
5번 열: (B, 2) 
6번 열: (B, 3)


남학생은 1,2,3,1,2,3,1,2,3... 이런식으로 반복된다는것을 알 수 있다. 이는 1부터 시작되는 자연수 집합을 3으로 나눈 후, 나머지를 갖는 관계이기도 하다. 즉, 1번열 -> 1, 2번열 -> 2, 3번열 -> 3, 4번열 -> 1, ... 이런 반복이 된다. 3,6,9 처럼 3으로 나뉘어 지는 수는 나머지가 0이다. 1,4,7 처럼 나머지가 1인 수도 있다. 2,5,8 처럼 나머지가 2인수 있다. 모든 자연수는 나머지를 0,1,2 중 하나를 갖는다. 

for(i in 1:nrow(x))
{
  # R에서 나머지를 계산하는 
  # operator는 %% 이다. 
  
  # 예를 들어, 4 %% 2 의 값은 0이다. 
  # 4를 2로 나누면 나머지가 0이다.
  
  # i 번째 row 를 남학생의 숫자로 나눈다. 
  # 이를 변수 k에 저장한다. 
  k <- i %% length(base)
  
  # 만약 k가 0이라면 
  # i번째 row의 숫자가 남학생 숫자의 배수라면 
  # k는 마지막 남학생을 뜻하는 숫자가 된다. 
  
  if (k == 0) {k<-length(base)}
  else{}
  
  # 남학생 집합내 숫자 중 1,2,3을 
  # matrix x의 2번째 컬럼에 저장한다. 
  # 1번째 row에는 1번째 남학생, 2번째 row 2번째, 
  # 3번째 3번째 남학생, 4번째 1번째 남학생, 
  # 5번째 2번째 남학생.. 이런 식이다. 
  
  x[i,2] <- base[k]
}

R에서 나머지를 계산하는 operator는 %% 이다. 
예를 들어, 4 %% 2 의 값은 0이다. 4를 2로 나누면 나머지가 0이다.

결과물:

> x
     [,1] [,2]
[1,]    0    1
[2,]    0    2
[3,]    0    3
[4,]    0    1
[5,]    0    2
[6,]    0    3


STEP 4: 본래 문제로 돌아가서, 3명의 여학생과 5명의 남학생으로 구성된 순서쌍을 출력해 보자. 

여학생 집합을 base1으로 표현하고, 각 여학생에게 숫자로 된 ID를 부여한다.
남학생 집합을 base2로 표현하고, 각 남학생에게 숫자로 된 ID를 부여한다.

 

base1 <- c(1:3)
base2 <- c(1:5)


순서쌍의 총 개수를 계산한다. 

length(base1)*length(base2)

 

matrix x를 만들고, (x,y) 순서쌍을 표현하기 위해 컬럼은 2개, number of rows는 순서쌍의 총 개수만큼 부여한다. 

x <- matrix(0, ncol=2, nrow=length(base1)*length(base2))



for ... loop 문을 사용하여 각 row 별 연산을 지시한다.

for (i in 1:nrow(x))
{
  # part 1: 남학생 매치
  if (i %% length(base2) == 0) {l <- length(base2)}
  else{l <- i %% length(base2)}
  x[i,2] <- base2[l]
  
  # part 2: 여학생 매치
  if (i %% length(base2) == 0) {k <- i %/% length(base2)}
  else {k <- i %/% length(base2) + 1}
  x[i,1] <- base1[k]
}

4- part 1: 남학생을 매치하자. 
i번째 row 를 남학생 숫자로 나누고, 나머지를 l에 저장한다. 만약 l 이 0이라면 (즉, i가 남학생 숫자의 배수라면), l은 마지막 남학생을 뜻하는 숫자가 된다. 

  if (i %% length(base2) == 0) {l <- length(base2)}

   
i번재 row를 남학생 숫자로 나눈 후, 나머지가 0이 아니라면, l에 나머지를 저장한다. 

else{l <- i %% length(base2)}


i번째 row의 두번째 column 값에 남학생을 뜻하는 숫자를 입력한다. 

  x[i,2] <- base2[l]



4- part 2: 여학생을 매치하자. 
몫을 계산하는 operator인 %/%를 사용한다. 예를 들어, 4 %/% 3 은 1이다. 4를 3으로 나누면 몫이 1이기 때문이다. 


1번째 row ~ 5번째 row까지는 1번째 여학생이, 6번째 row ~ 10번째 row까지는 2번째 여학생이, 11번째 ~ 15번째 row 까지는 3번째 여학생이  매치된다. i번째 row를 남학생 숫자인 5로 나눈 후, 해당되는 몫의 숫자에 1을 더해 여학생이 매칭된다. 즉, 7번째 row는 1) 7을 5로 나누고, 2) 몫인 1에 1을 더해 2를 산출 한 후, 3) 2번째 여학생을 매치한다. 


위 방법은 남학생 숫자의 배수에 해당되는 i 에는 에러가 발생한다. 이를 해결하기 위해, 남학생 숫자의 배수에 해당되는 i에는 남학생 숫자를 나눈 몫을 지정한다. 즉, 5번째 row에는 5 나누기 5인 1이므로 1번 여학생, 10번째 row에는 2번째 여학생인 것이다.    

  if (i %% length(base2) == 0) {k <- i %/% length(base2)}
  else {k <- i %/% length(base2) + 1}

i번째 row의 첫번째 column 값에 여학생을 뜻하는 숫자를 입력한다. 

  x[i,1] <- base1[k]

 

# 마지막으로 x matrix를 출력한다. 

> print(x)
      [,1] [,2]
 [1,]    1    1
 [2,]    1    2
 [3,]    1    3
 [4,]    1    4
 [5,]    1    5
 [6,]    2    1
 [7,]    2    2
 [8,]    2    3
 [9,]    2    4
[10,]    2    5
[11,]    3    1
[12,]    3    2
[13,]    3    3
[14,]    3    4
[15,]    3    5

 

STEP 5: step 4 코드가 기존 여학생들과 남학생들 이름을 대체하여도 작동하는지 확인해 보자. 

base1 <- c('영희', '수진', '미현')
base2 <- c('진수', '경호', 
           '윤호', '명진', '기철')

length(base1)*length(base2)

x <- matrix(0, 
            ncol=2, 
            nrow=length(base1)
            *length(base2))


for (i in 1:nrow(x))
{
  if (i %% length(base2) == 0) 
    {l <- length(base2)}
  
  else
    {l <- i %% length(base2)}
  
  x[i,2] <- base2[l]
  
  
  
  if (i %% length(base2) == 0) 
    {k <- i %/% length(base2)}
  else 
    {k <- i %/% length(base2) + 1}
  
  x[i,1] <- base1[k]
}

결과물

> print(x)
      [,1]   [,2]  
 [1,] "영희" "진수"
 [2,] "영희" "경호"
 [3,] "영희" "윤호"
 [4,] "영희" "명진"
 [5,] "영희" "기철"
 [6,] "수진" "진수"
 [7,] "수진" "경호"
 [8,] "수진" "윤호"
 [9,] "수진" "명진"
[10,] "수진" "기철"
[11,] "미현" "진수"
[12,] "미현" "경호"
[13,] "미현" "윤호"
[14,] "미현" "명진"
[15,] "미현" "기철"

comment: 적절하게 작동하는 모습이다.

compute 2080의 블로그

https://compute2080.tistory.com/

 

Compute2080: 금융공학, 프로그래밍, 정량화(quantify)

 

compute2080.tistory.com