R은 동적 타입 언어(Dynamically typed language)이기 때문에 변수의 자료형을 마음대로 바꿀 수 있다는 장점이 있다.
또한 다양한 통계, 시각화 패키지들이 존재하여 손쉽게 꺼내쓸 수 있다는 점이다. 또한 오픈소스이고 직관적이고 쉽게 데이터 전처리가 가능하다는 점이다.
하지만 단점으로는 모든 데이터를 메모리에 로딩한 후 처리하기에 속도 측면에서 불리하다. 불필요한 데이터 저장으로 메모리 부족 현상이 일어난다.
1) Cat
cat 함수는 print의 대안으로, 여러 개의 항목을 묶어서 출력할 때 쓰임
추가로 한 줄을 끝내고 싶을 때에는 \n 개행 문자 삽입
하지만 행렬이나 리스트 같은 데이터 구조는 출력할 수 없다는 점
> cat(pi, 2*pi, sqrt(3))
3.141593 6.283185 1.732051
# 하지만 행렬이나 리스트 같은 데이터 구조는 출력 불가능
> cat(list("a", "b", "c"))
Error in cat(list("a", "b", "c")) :
argument 1 (type 'list') cannot be handled by 'cat'
2) ls, ls.str()
변수들의 목록을 보고 싶을 때에는 ls 함수를 사용
ls.str()로 각 변수의 자세한 내용을 볼 수 있다. 만약 작업공간이 비어 있는 경우에서 ls함수를 사용 시 character(0)을 반환한다. 즉 작업공간에 정의 된 것이 없기에 빈 벡터를 반환한다.
# ls함수를 사용하여 변수 목록을 볼 수 있다.
# 더 자세하게 보려면 ls.str()
> x <- 10
> y <- 50
> z <- c("three", "blind", "mice")
> f <- function(n, p) sqrt(p * (1-p) / n)
> ls()
[1] "airquality" "economics" "exdata1" "f" "fib"
[6] "geo_code" "geo_data" "gg_daejeon" "gr_cyl" "idx"
[11] "melt_test" "mp_rank" "mtcars" "pre.rf" "r.f"
[16] "test.data" "train.data" "x" "x_inter" "y"
[21] "z"
> ls.str()
x : num 10
x_inter : Date[1:1], format: "2005-07-01"
y : num 50
z : chr [1:3] "three" "blind" "mice"
3) 벡터 생성 c(...)
벡터를 생성할 떄 c(...) 연산자를 사용
벡터는 숫자, 문자열, 논리값 중 한 가지만 포함하고 이들을 서로 섞어서 쓸 순 없다, 섞는 경우 둘 중 하나의 데이터 형식으로 통일 된다.
추가적으로 c는 제네릭 연산자로써, 벡터뿐만 아니라 다른 많이 데이터 형식과도 작동한다는 것이다.
# c(...) 연산자를 이용하여 생성
# 벡터는 숫자, 문자열, 논리값 중 한 가지만 포함하여 이들을 섞을 수 X
> c(1,1,2,3,5,8,13,21)
[1] 1 1 2 3 5 8 13 21
> c(TRUE,TRUE,FALSE)
[1] TRUE TRUE FALSE
# 벡터 하나로 합치기
> v1 <- c(1,2,3)
> v2 <- c(4,5,6)
> c(v1, v2)
[1] 1 2 3 4 5 6
# 데이터 형식을 섞어서 만들 수는 없음, 섞는다면 둘 중 하나로 데이터 형식이 통일됨
> v1 <- c(1,2,3)
> v3 <- c("A", "B", "C")
> c(v1,v3)
[1] "1" "2" "3" "A" "B" "C" # 문자열로 통일됨
4) 통계량 확인
통계량을 알아보고 싶을 떄에는 mean, sd, cor, median 등 함수를 사용하면 된다
# 산술평균 : mean(x) 표준편차 : sd(x) 상관계수 : cor(x,y)
# 중앙값 : median(x) 분산 : var(x) 공분산 : cov(x,y)
> x <- c(0,1,1,2,3,5,8,13,21,34)
> mean(x)
[1] 8.8
> median(x)
[1] 4
> sd(x)
[1] 11.03328
> var(x)
[1] 121.7333
# 상관계수, 공분산
> x <- c(0,1,1,2,3,5,8,13,21,34)
> y <- log(x + 1)
> cor(x,y)
[1] 0.9068053
> cov(x,y)
[1] 11.49988
# 결측치 : NA, 결측치 포함시 모든 함수에서 NA 반환
> x <- c(0,1,1,2,NA)
> mean(x)
[1] NA
# na.rm = TRUE로 결측치 제거
> x <- c(0,1,1,2,NA)
> mean(x, na.rm=TRUE)
[1] 1
5) 수열 생성
수열을 생성할 때에는 :, rep, seq를 쓴다
숫자 : 숫자 사용시에는 공차가 1인 등차수열을 만들 수 있고 역으로도 가능하다
rep의 의미는 repetition 반복한다는 의미로, 특정값을 반복할 떄 쓰인다.
추가로 rep은 숫자 뿐만 아니라 문자열도 반복이 가능하다.
seq은 시작숫자, 끝 숫자를 정해주면 숫자를 생성한다. from과 to인자를 통해 시작과 끝을 정하고
length.out을 통해 값 길이를 지정할 수 있다.
# n:m 표현식을 사용
> 1:5
[1] 1 2 3 4 5
> 5:1
[1] 5 4 3 2 1
# 1이 아닌 수치로 증가하는 수열에는 seq 함수 사용
> seq(from = 1, to = 5, by = 2)
[1] 1 3 5
# rep 함수를 사용해 반복되는 값들로 된 수열 생성
> rep(1, times = 10)
[1] 1 1 1 1 1 1 1 1 1 1
# 수열 결과 값 길이 지정
> seq(from = 0, to = 7, length.out = 6)
[1] 0.0 1.4 2.8 4.2 5.6 7.0
6) 벡터에 있는 원소 선택하기
주로 인덱스를 사용하는 방법이 있다.
예를 들어 v의 4번쨰 원소를 선택하려면 v[4]
여기서 중요한 점은 python이나 다른 인덱스 처럼 인덱스가 0부터 시작하는게 아닌 1부터 시작한다는 점이다.
원소를 제외할 떄에는 인덱스를 음수로 쓰고 이름이 붙여진 원소에 접근하려면 이름을 사용하면 된다.
# 원소 선택시 인덱스 사용[]
# 이름 붙여진 원소에 접근하려면 이름을 사용
# 원소를 제외하고 싶으면 인덱스를 음수로 씀
> fib <- c(0,1,1,2,3,5,8,13,21,34)
> fib[1]
[1] 0
> fib[5]
[1] 3
> fib[6]
[1] 5
> fib[1:3]
[1] 0 1 1
> fib[-1]
[1] 1 1 2 3 5 8 13 21 34
> fib[c(1,2,4,8)]
[1] 0 1 2 13
# 인덱스 응용
# 비교, 논리 연산자, 벡터의 인덱스를 합쳤을 떄
> v <- c(3,6,1,9,11,16,0,3,1,45,2,8,9,6,-4)
> v[v > median(v)] # 중앙값 보다 큰 모든 원소 선택
[1] 9 11 16 45 8 9
> v[(v < quantile(v,0.05)) | (v > quantile(v,0.95))] # 상, 하위 5% 안에 있는 모든 원소 선택
[1] 45 -4
> v[abs(v - mean(v)) > sd(v)] # 평균에서 +-1 표준편차를 넘는 모든 원소 선택
[1] 45 -4
# 인덱스를 이름으로 선택
> years <- c(1960, 1975, 1990)
> names(years) <- c("Kennedy", "Carter", "Clinton")
> years
Kennedy Carter Clinton
1960 1975 1990
> years["Carter"]
Carter
1975
7) 벡터의 연산 수행
기본적인 산술 연산자들은 모두 벡터 쌍에 대해 적용 가능하며 각 원소별로 연산을 수행한다.
여기서 주의할 점은 결과값의 길이가 원본 벡터의 길이와 일치해야 된다.
> v <- c(11,12,13,14,15)
> w <- c(3,4,5,6,7)
> v + w
[1] 14 16 18 20 22
> v - w
[1] 8 8 8 8 8
> v / w
[1] 3.666667 3.000000 2.600000 2.333333 2.142857
> v - 2
[1] 9 10 11 12 13
> v - mean(w)
[1] 6 7 8 9 10
> x <- 1 : 10
> sqrt(x)
[1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751
[8] 2.828427 3.000000 3.162278
8) 연산자의 우선순위
R에서는 연산자 우선순위가 다음 표와 같다.
연산자 | 뜻 |
[ [[ | 인덱스 |
:: ::: | 네임스페이스 |
$ @ | 요소 뽑아내기, 슬롯 뽑아내기 |
^ | 지수 |
- + | 단항 마이너스, 플러스 부호 |
: | 수열 생성 |
%any%(%>%포함) | 특수 연산자 |
* / | 곱하기, 나누기 |
+ - | 더하기, 빼기 |
== != < > <= >= | 비교 |
! | 논리 부정 |
& && | 논리 "and" |
| || | 논리 "or" |
~ | 식 |
-> ->> | 오른쪽 대입 |
= | 대입(오른쪽을 왼쪽으로) |
<- <<- | 대입 (오른쪽을 왼쪽으로) |
? | 도움말 |
9) 함수 호출 파이프라인 만들기
파이프 연산자(%>%)를 사용해 표현식을 읽고 쓰기 쉽게 만든다. 수많은 tidyverse 함수에서도 폭넓게 사용되고 있다.
> library(tidyverse)
> data(mpg)
> mpg %>%
+ filter(cty > 21) %>%
+ head(3) %>%
+ print()
# A tibble: 3 × 11
manufacturer model displ year cyl trans drv cty hwy fl
<chr> <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr>
1 chevrolet malibu 2.4 2008 4 auto(… f 22 30 r
2 honda civic 1.6 1999 4 manua… f 28 33 r
3 honda civic 1.6 1999 4 auto(… f 24 32 r
# … with 1 more variable: class <chr>
x %>% head()는 head(x)와 기능적으로 동일하다
두 경우 모두 x는 head의 인자이고 추가적인 인자 전달이 가능하지만, x는 언제나 첫 번째 인자가 된다.
x %>% head(n = 10)
head(x, n = 10)
위의 경우 기능적으로 동일한 예시이다. 하지만 예제가 복잡해질수록 이점이 늘어나며 작업 와중에 filter를 사용해서 데이터를 값으로 한정하고, select를 사용해서 특정 값들만 남겨 두고, ggplot에 보내서 간단한 그래프를 그린다고 할 때 중간 단계 변수를 사용 할 수 있다.
library(tidyverse)
filtered_mpg <- filter(mpg, cty > 21)
selected_mpg <- select(filtered_mpg, cty, hwy)
ggplot(selected_mpg, aes(cty, hwy)) + geom_point()
mpg %>%
+ filter(cty > 21) %>%
+ select(cty, hwy) %>%
+ ggplot(aes(cty,hwy)) + geom_point
추가적으로 앞의 코드는 mpg 데이터세트에서 filter 함수로 파이프하며 도심 mpg 값인 cty 변수가 21보다 큰 레코드들만 남겨 두는 것이다. 확실히 파이프라인을 사용하는 것이 더 가독성이 좋고 더 편한 점이 있다.
'데이터분석 > R' 카테고리의 다른 글
R언어 공부 - 6 (0) | 2022.12.30 |
---|---|
R언어 공부 - 5 (3) | 2022.12.29 |
R언어 공부 - 4 (0) | 2022.12.27 |
R언어 공부 - 3 (0) | 2022.12.27 |
R언어 공부 - 2 (0) | 2022.12.26 |