(10주차) 11월16일
리스트
options(jupyter.rich_display=FALSE)
-
(1/5) 리스트 (1)
-
(2/5) 리스트 (2)
-
(3/5) 리스트 (3)
-
(4/5) 리스트 (4)
-
(5/5) 리스트 (5)
-
중간고사와 비슷하게 낼 예정. 범위도 거의 비슷.
-
중간고사때 까지의 내용만 극한으로 단련해도 어느정도는 풀 수 있을 거에요.
-
코드를 좀 더 예쁘게 효율적으로 만들기 위한 다양한 문법 및 기능이 필요한데 중간~기말 이후에는 그것을 채우는 과정
-
수업목표:
- 문제상황 (어떠한 것을 계산해야 하는 일이 생길때) 알고리즘을 머리속에 떠올릴 수 있다.
- 머리속에 떠올린 알고리즘을 기본적인 제어문과 반복문을 통하여 구현할 수 있다. (이미 한 내용, 그런데 지금부터는 좀 더 예쁘고 효율적으로 구현하는 방법을 설명하겠습니다)
-
이상한 자료형
-
제가 굉장히 많이 사용하는 자료형태.. 그런데 왜 쓰는지 이유를 물어보면 딱히 잘 모르겠어요
-
리스트를 선언하는 방법
lst = list(5:10,c("A","B","C"),matrix(c(T,T,F,T),ncol=2))
lst
- 리스트의 첫번째 원소 = 숫자로 이루어진 벡터
- 리스트의 두번째 원소 = 문자로 이루어진 벡터
- 리스트의 세번째 원소 = True / False로 이루어진 매트릭스
-
리스트의 각 원소를 추출하는 방법
lst[[1]]
lst[[2]]
lst[[3]]
lst[[1]]+3
-
리스트의 길이
length(lst)
-
왜 리스트를 쓰는가? (1) 함수에서 여러개의 리턴값을 주는 효과 (2) 정리의 효과
- 명확한 이점: 함수의 리턴값을 여러개
- 그외의 이점: 저도 솔직히 잘 모르겠어요.
- 벡터, 매트릭스, 데이터프레임와 같이 기능상의 이점이 있는것 같진 않아요.
- 그런데 자료를 저장하고 정리하기에 좋아요 (제가 정리하는걸 좋아하는것 같아요)
mid = list(c('hynn','iu','gd'),c(100,95,100))
mid
names(mid)
names(mid)<-c('names','score')
mid
-
보기에 깔끔하다.
-
데이터에 접근하기도 좋다.
mid$names
mid$score
-
물론 아래와 같이 접근할수도 있다.
mid[[1]]
mid[[2]]
-
리스트를 복사후 재생성하기에 좋음
mid
final = mid
final
final$score = mid$score - 10
final$score
final
-
리스트를 묶어서 새로운 리스트를 또 만들 수도 있음
IR2021 <- list(mid,final)
IR2021
-
리스트원소에 이름을 붙여주면
names(IR2021)
names(IR2021) <- c("mid","final")
IR2021
IR2021$final$score
-
아래와 같이 선언하는 것도 깔끔해보인다.
IR2021 = list(names=mid$names, mid=mid$score, final=final$score) # 리스트의 구성요소와 이름을 동시에 선언
IR2021
IR2021
IR2021[1]
IR2021[1:2]
IR2021[c(1,3)]
IR2021[-2]
IR2021[[1]]
IR2021[[2]]
-
아래는 동작하지 않음
IR2021[[-1]]
-
아래는 의도와 다르게 동작함
IR2021[[1:2]]
IR2021[[c(1,2)]]
- IR2021[[1]][2]와 결과가 같음
IR2021[[1:3]]
IR2021[[c(1,3)]]
#IR2021[[1]][3]
IR2021$names
IR2021[['names']]
-
언뜻 생각하면 IR2021$names
와 IR2021[['names']]
의 기능은 같으므로 이 경우에는 $
와 [[
를 서로 바꿔도 될것 같다. 하지만 항상 그런 것은 아니다.
IR2021$n
IR2021[['n']]
-
즉 $
연산자와 [[
연산자의 차이는 파샬매칭(partial matching)을 허용하느냐 하지않느냐의 차이다.
IR2021$n
IR2021$na
IR2021$name
- 특히 마지막 IR2021$name은 마치 오타를 허용해주는 느낌이다.
-
그런데 아래는 동작하지 않음
IR2021$ames
IR2021$es
-
R에서는 일반적으로 하나의 오브젝트만 리턴함
-
하지만 리스트를 사용하면 다중리턴을 지원하는 것처럼 느낄 수 있음.
cal= function(x,y){
return(list(add=x+y, sub=x-y, mul=x*y, dic=x/y))
}
cal(2,3)
-
이런일이 있으면 그냥 cal_add, cal_mul, cal_sub, cal_div 처럼 함수를 4개 구현하면 되는것이 아닌가? $\to$ 물론 그래도 가능하지만 코드가 지저분해 지니까
-
함수의 결과값을 저장하여 아래와 같이 사용
rslt = cal(4,3)
rslt$add
rslt$sub
-
아래와 같이 쓰지는 않음
cal(4,3)$add
cal(4,3)$sub
-
기본적인 자료형 vector, matrix, list에 기능을 스스로 정리해보고 요약해볼것 (제출의무 없음)
- 벡터의 길이를 재려면 어떻게 해야하는지?
- 매트릭스의 차원은 어떻게 알 수 있는지?
- 리스트의 원소에 접근하려면?
- $n\times 1$ 매트릭스 혹은 $1\times n$ 매트릭스를 쓰면 되는데 왜 굳이 벡터를 만들었을까?
-
벡터 ${\bf x}$와 벡터 ${\bf y}$를 아래의 코드를 이용해 표준 정규분포에서 생성하라. (표준정규분포를 모른다면 질문하거나 네이버 구글에서 스스로 찾아볼것)
x=rnorm(100)
y=rnorm(100)
아래의 수식을 계산하는 코드를 작성하라.
$$\frac{\sum_{i=1}^{100}(x_i-\bar{x})(y_i-\bar{y})}{\sqrt{\sum_{i=1}^{100}(x_i-\bar{x})^2}\sqrt{\sum_{i=1}^{100}(y_i-\bar{y})^2}}$$
단 $\bar{x}=\frac{1}{100}\sum_{i=1}^{100}x_i$로 정의한다.
x=rnorm(100)
y=rnorm(100)
보충학습
x
${\bf x} = (x_1,x_2,\dots, x_{100})=(-1.34195186 ,-0.85612995,\dots, -0.87349548)$
$\frac{1}{100}\sum_{i=1}^{100} x_i =\frac{1}{100}(x_1+x_2+\dots +x_{100})=\frac{1}{100}(-1.34195186 + (-0.85612995) + \dots (-0.87349548))$
코드상으로는 아래와 같이 계산할 수 있겠음
sum(x)/100 # xbar
mean(x)
(풀이)
$$\frac{\sum_{i=1}^{100}(x_i-\bar{x})(y_i-\bar{y})}{\sqrt{\sum_{i=1}^{100}(x_i-\bar{x})^2}\sqrt{\sum_{i=1}^{100}(y_i-\bar{y})^2}}=\frac{A}{BC}$$
A=0
for (i in 1:100) A=A+(x[i]-mean(x))*(y[i]-mean(y))
A
B=0
for (i in 1:100) B=B+(x[i]-mean(x))**2
B=sqrt(B)
B
C=0
for (i in 1:100) C=C+(y[i]-mean(y))**2
C=sqrt(C)
C
A/(B*C)
(다른풀이)
sum((x-mean(x))*(y-mean(y))) / (sqrt(sum((x-mean(x))**2)) * sqrt(sum((y-mean(y))**2)))
(다른풀이2)
벡터의 내적: ${\bf x}=(x_1,\dots,x_{100})$ 라고 하고, ${\bf y}=(y_1,\dots,y_{100})$ 라고 할때 두 벡터의 내적은 아래와 같이 계산한다.
$${\bf x} \cdot {\bf y} = x_1 y_1 + \dots + x_{100}y_{100}$$
x_ <- c(1,2,3)
y_ <- c(2,3,4)
x_ %*% y_
1*2+ 2*3+ 3*4
이러한 성질을 이용하면
xx= x-mean(x)
yy= y-mean(y)
((xx %*% yy) / (sqrt(xx %*% xx )* sqrt(yy %*% yy )))