(7주차) 10월22일
프로그래밍의 중요성, 숫자카드게임 apply함수를 이용한 풀이, 매트릭스 선언방법, 매트릭스에서 원소를 추출하는 방법, 매트릭스를 사용할시 얻는 이점, apply함수 사용법, for와 apply코드시간비교
-
(1/4) 프로그래밍의 중요성
-
(2/4) 숫자 카드 게임 apply함수를 이용한 풀이, 매트릭스 선언방법, 매트릭스에서 원소를 추출하는 방법
-
(3/4) 매트릭스를 사용할시 얻는 이점, apply함수 사용법 (1)
-
(4/4) apply함수 사용법 (2), for와 apply코드시간비교, 과제설명
숫자 카드 게임은 여러개의 숫자중에서 가장 높은 숫자가 쓰인 카드를 한장 뽑는 게임이다.
단, 게임의 룰을 지키며 카드를 뽑아야 하고 룰은 다음과 같다.
- 숫자가 쓰인 카드들이 N$\times$M 형태로 놓여 있다.
- 먼저 뽑고자 하는 카드가 포함되어 있는 행을 선택한다.
- 그 다음 선택된 행에 포함된 카드들 중에서 가장 숫자가 낮은 카드를 뽑아야 한다.
- 따라서 처음에 카드를 골라낼 행을 선택할때, 이후에 해당 행에서 가장 숫자가 낮은 카드를 뽑을 것을 고려하여 최종적으로 가장 높은 숫자의 카드를 뽑을 수 있도록 전략을 세워야 한다.
-
예시1
입력
3 1 2
4 1 4
2 2 2
출력
2
-
예시2
입력
7 3 1 8
3 3 3 4
출력
3
입력구조가
3 4 5 1
7 7 7 2
8 1 8 2
3 3 4 5
와 같을 때 출력을 구하는 코드를 작성하시오.
(숙제풀이)
library(tidyverse)
A=rbind(c(3,4,5,1),c(7,7,7,2),c(8,1,8,2),c(3,3,4,5))
A
step1 apply 함수를 사용하여 각 row의 min을 구한다.
apply(A,1,min) # A=입력매트릭스, 1=입력매트릭스의 각 row에 어떠한 함수를 적용
A %>% apply(1,min)
step2. step1의 결과에 max를 취한다.
max(apply(A,1,min))
A %>% apply(1,min) %>% max
-
방법1: 벡터를 만들고, 그것을 row-vector로 해석한뒤 $\to$ bind
rbind(c(1,2,3,4),c(2,3,4,5))
-
방법2: 벡터를 만들고, 그것을 col-vector로 해석한뒤 $\to$ bind
cbind(c(1,2,3,4),c(2,2,3,4))
참고: 만들어진 매트릭스의 차원을 살펴보는 방법
A=rbind(c(1,2,3,4),c(2,3,4,5))
dim(A)
A=cbind(c(1,2,3,4),c(2,2,3,4))
dim(A)
-
방법3: 벡터를 선언하고 dim()을 이용하여 차원을 강제셋팅
A = 1:8
A
dim(A)
dim(A) <- c(2,4)
dim(A)
A
dim(A) <- c(4,2)
A
dim(A) <- c(3,3)
-
일단 이정도 까지만..
-
아래와 같은 매트릭스가 있다고 하자.
A=rbind(c(1,2,3,4),c(5,6,7,8),c(9,10,11,12))
A
-
1열을 뽑고싶다.
A[,1]
-
1열,4열을 뽑고싶다.
A[,c(1,4)]
-
2행을 뽑고싶다.
A[2,]
-
1행과 2행을 뽑고싶다.
A[c(1,2),]
-
2행3열의 원소를 뽑고싶다. 즉 (2,3)의 위치에 있는 원소를 뽑고싶다.
A[2,3]
-
일단 이정도만..
-
바둑판구조의 자료형을 표현하기 위해서 = 자료를 바둑판 구조로 저장하기 위해서
-
자료를 바둑판(2d-array), 나아가 큐브형태(3d-array)로 저장하면 어떠한 이점이 있는가?
-
자료를 벡터(1d-array)로 저장하면 어떠한 이점이 있는가? 와 같은 질문
- 프로그래밍 구조상의 이점
- 계산상의 이점
(예시) 초항이 1이고 공차가 2인 등차수열을 100개 만들어라.
(풀이1)
a<-c()
for (n in 1:100) a[n] = 2*n-1
a
위와 같은 간단한 코드도 결국 벡터형태로 자료를 저장하고 관리하기 때문에 for를 쓸 수 있는것임
(풀이2)
n=1:100
2*n-1
이것역시 벡터의 개념이 있기 때문에 가능함
-
자료를 벡터로 관리하면 어떠한 이점이 생기듯이 자료를 매트릭스로 관리해도 이점이 생긴다.
-
우선 아래를 기억하자.
apply(매트릭스,1,특정함수)
를 쓰면 어떠한 특정함수가 각각의 row에 적용되어서 결과가 array로 저장된다.
-
여기에서 특정함수는 "벡터입력-스칼라출력" 이라 생각하자. 즉 벡터입력-스칼라출력인 함수만 apply가 가능하다고 생각하자. (사실 그렇지는 않음) 예를들면 아래와 같다.
sum(c(1,2,3,4))
mean(c(1,2,3,4))
-
아래와 같은 함수는 벡터입력-벡터출력 이므로 조건에 해당하지 않는다.
sqrt(c(1,2,3,4))
-
이제 매트릭스 A에 다양한 함수를 적용해보자.
A
apply(A,1,sum)
apply(A,1,mean)
apply(A,1,min)
apply(A,1,max)
사용자가 임의로 정의한 함수도 가능하다.
f = function(a) (min(a)+1)**2-3
apply(A,1,f)
-
숫자1을 2로 바꾸면 특정함수가 각각의 col에 적용되어서 결과가 array로 저장된다.
A
apply(A,2,sum)
apply(A,2,mean)
apply(A,2,min)
apply(A,2,max)
apply(A,2,f)
-
아래는 같은코드이다.
sum(1:10)
1:10 %>% sum()
1:10 %>% sum
-
아래와 같이 2개의 입력을 받는 함수를 생각하자.
myfun = function(x,y) x**2+y
myfun(2,3)
-
아래는 같은코드이다.
myfun(2,3)
2 %>% myfun(3)
-
동일한 논리로 아래도 같은코드이다.
myfun(3,2)
3 %>% myfun(2)
-
입력이 3개인 함수를 만들자.
myfun2= function(x,y,z) x**2 + y*z
-
아래는 같은코드이다.
myfun2(2,1,1)
2 %>% myfun2(1,1)
-
왜 이러한 일을 해야하는가? (합성함수 처리에 유리)
2:5 %>% log %>% sqrt %>% sum %>% myfun2(1,1) %>% sqrt
sqrt(myfun2(sum(sqrt(log(2:5))),1,1))
2:5 %>% log %>% myfun(3) %>% sqrt %>% sum %>% myfun2(1,1) %>% sqrt
sqrt(myfun2(sum(sqrt(myfun(log(2:5),3))),1,1))
-
아래의 개념차이
- $g(h(f(x)))$
- $x \to f \to h \to g$
-
시간비교하는 방법
t1=Sys.time()
t2=Sys.time()
t2-t1
-
큰 매트릭스 만듬
A=sample(1:9,size=100*2000000,replace=TRUE)
dim(A)<-c(2000000,100)
A
t1=Sys.time()
A %>% apply(1,min) %>% max
t2=Sys.time()
t2-t1
t1=Sys.time()
vec<-c()
for(i in 1:(dim(A)[1])) vec[i]<-min(A[i,])
max(vec)
t2=Sys.time()
t2-t1
-
for문이 좀더 빠르지만 코드는 apply가 더 간결해보인다.
-
아래의 코드를 실행하고 실행결과를 제출
t1=Sys.time()
A %>% apply(1,min) %>% max
t2=Sys.time()
t2-t1
t1=Sys.time()
vec<-c()
for(i in 1:(dim(A)[1])) vec[i]<-min(A[i,])
max(vec)
t2=Sys.time()
t2-t1