웅진X유데미 STARTERS/TIL (Today I Learned)

[스타터스 TIL] 11일차.기초부터 익히는 R (1) - R 자료 구조, 변수, 함수, 패키지

라밍쏭 2023. 2. 20. 16:59
728x90


1. R 이란?

- 전산통계학을 위한 프로그래밍 언어

-  데이터 통계처리 및 시각화에 특화되어 있음

 

1.1 R의 장단점

✅ 장점

언어적 측면

- 통계 계산용 패키지 매우 우수 → dplyr, tidyr, stringr, lubridate

- 강력한 시각화 패키지 제공 → ggplot2, rgl, htmlwidgets

- 뛰어난 확장성 → 웹기반 분석결과 리포팅 (ggvis, shiny), 인공지능 연구(lme4/nlme, randomForest, caret, deepnet)

 

사용자 측면

- 유저 커뮤니티 활성화 → 대부분의 유저들이 유사한 목표를 가짐, 디버깅 용이

- 상대적으로 학습 난이도 낮음

- 다양한 os 지원

- 무료

 

✅ 단점

- 느린 속도 : 범용 프로그래밍 언어보다 처리 속도 느림

- 한정된 사용성 : 대규모 IT 서비스 개발에 접목이 어려움

- 보안 기능 없음

 

1.2 데이터 마이닝이란?

- Data + Mining = '데이터'로부터 정보를 '채굴'

- 데이터 모집단의 패턴을 찾아 새로운 데이터를 예측, 군집화, 분류하기 위함

- R은 데이터 마이닝을 하기 위해 사용함

 

1.3 R 활용 가능 분야

- 텍스트 마이닝 : 방대한 텍스트 정보를 크롤링하고 단어 빈도순으로 가중치를 두어 시각화함

- 소셜 네트워크 분석 : 사람 간 관계 시각화 (SNS 팔로우, 친구 추가 데이터 사용)

- 지도 시각화

- 주식 분석 : 통계 패키지를 사용한 주가 예측

- 이미지 분석 : 이미지 라벨링, 이미지 구획 나누기

- 사운드 분석 : 아날로그 소리 데이터를 디지털 벡터 데이터로 변환

- 웹 애플리케이션 개발

 

1.4 데이터 처리 과정에서 R의 역할


2. R 기본 기능

2.1 데이터 타입 & 객체

- Object (객체) : R이 다루는 가장 기초적인 구조

- Class : 객체의 타입 (class() 함수 사용)

데이터 타입 설명
Numeric (수치형) 숫자를 나타내는 데이터 타입
Integer (정수형) 정수 값만 나타내는 데이터 타입 (메모리 관리에 효율적)
Logical (논리형) 참, 거짓을 나타내는 데이터 타입 (TRUE, FALSE, T, F)
Character (문자형) 문자 또는 문자열을 나타내는 데이터 타입

 

데이터 객체 설명
Inf (Infinity) 무한히 큰 값을 나타내는 데이터 객체
NA (Not Available) 결측치를 나타내는 데이터 객체
NaN (Not a Number) 수치값으로 표현할 수 없는 값을 나타내는 데이터 객체

 

 

2.2 R 자료 구조

 

✅ 벡터 (Vector)

- 1차원 구조

- 데이터 타입이 동일한 값들의 모음

- 생성 방법 : c(데이터) / vector('데이터 타입', length = 벡터크기)

## 생성 방법 1
c(1, 2, 3)
# [OUT] 1 2 3

c('a', 'b', 'c')
# [OUT] "a" "b" "c"

c(T, T, F)
# [OUT]  TRUE  TRUE FALSE

## 생성 방법 2
# 생성 시 각 자료형 별 디폴트 값 : "", 0, FALSE
vector('character', length = 5)
# [OUT] "" "" "" "" ""

vector('numeric', length = 5)
# [OUT] 0 0 0 0 0

vector('logical', length = 5)
# [OUT] FALSE FALSE FALSE FALSE FALSE

 

- 벡터에 서로 다른 데이터 타입을 넣으면 자동 형 변환이 일어남

- 자동 형변환 우선 순위 : Character > Numeric > Logical

c(1.7, 'a')  # 숫자형 → 문자형으로 변환
# [OUT] "1.7" "a"

c(TRUE, 2)  # 논리형 → 숫자형으로 변환
# [OUT] 1, 2

c('a', TRUE)  # 논리형 → 문자형으로 변환
# [OUT] "a"    "TRUE"

 

 

✅ 행렬 (Matrix)

- vector의 집합

- 단일형, 2차원 데이터 자료 구조

- 생성 방법 : matrix(nrow = 행 크기, ncol = 열 크기)

# 2X3 크기의 행렬 생성
matrix(nrow = 2, ncol = 3)  

# 데이터를 추가해서 행렬 생성
matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3) # 데이터 추가

# 데이터를 행부터 채우기 (기본값 F)
matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3, byrow = T)

 

- 행렬의 데이터 타입

   → 행/열 크기를 담는 dim 속성을 추가로 가짐

   → Matrix == dim 크기가 2인 array

class(matrix(nrow = 2, ncol = 3))
# [OUT] "matrix" "array"

 

 

✅ 배열 (Array)

- dim 속성 크기가 2 이상인 자료 구조

- 단일형, 2차원 데이터 자료 구조

- 생성 방법 : array(dim = c(데이터))

# 2행 2열인 행렬의 3층짜리 배열 만들기
array(dim = c(2, 2, 3))

 

# 데이터 추가하여 배열 만들기
array(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), dim = c(2, 2, 3))

 

 

✅ 리스트 (List)

- 서로 다른 데이터 타입이 존재하는 값들의 모음 (다중형 데이터 자료 구조)

- 생성 방법 : list()

list(c(1,2,3), 2, T)

 

# 리스트 내 리스트 생성 (이중 리스트 생성)
list(list(1, T, 'a'), 1)

 

# 리스트 내 matrix도 가능
list(matrix(nrow = 2, ncol = 3), 'a', 5)

 

 

✅ 데이터 프레임

- list의 집합 (다중형, 2차원 구조)

- 열 별로 다른 데이터 타입 저장 가능

- 생성 방법 : data.frame(vector, vector, ...)  → 각 vector는 컬럼 값으로 삽입됨

data.frame(c(1,2,3,4,5), c('a', 'b', 'c', 'd', 'e'), c(T, T, F, T, T))

 

# 변수로 데이터 프레임 생성
ID <- c(1,2,3,4,5)
Grade <- c('a', 'b', 'c', 'd', 'e')
Pass <- c(T, T, F, T, T)

data.frame(ID, Grade, Pass)

 

 

 

 

2.3 변수

- 데이터를 저장하기 위해 이름을 할당 받은 메모리 공간

- 객체(Object)를 저장해 놓는 보관함

 

✅ 변수 초기화

# 변수 선언만 하고 싶은 경우
a <- NULL
a  # [OUT] NULL

# 변수에 값 할당
a <- 10
a  # [OUT] 10

 

✅ 변수 할당

# 연산의 결과를 할당 가능
a <- 10 + 20   # [OUT] 30
b <- a - 5   # [OUT] 25
c <- c(1, 2, 3) + 5   # [OUT] 6, 7, 8
d <- (10 > 5)   # [OUT] TRUE
e <- b + d   # [OUT] 26


# 하나의 객체만 저장 가능
a <- 5, 10  # Error: unexpected ',' in "a <- 5,"


# 한 번에 여러 변수 선언 및 할당 불가
a, b <- 5, 10  # Error: unexpected ',' in "a,"


# 특별한 데이터 타입 할당 가능
a <- Inf  # [OUT] Inf
b <- 2/0  # [OUT] Inf
c <- NA   # [OUT] NA
d <- NaN  # [OUT] NaN
e <- 0/0  # [OUT] NaN

 

✅ 변수 작명 규칙

- 첫글자 : 문자 또는 마침표(.)만 사용 가능 (숫자, 언더바로 변수명 시작 불가)

- 알파벳 대분자와 소문자는 별개의 문자 취급

- 변수명 중간에 빈 칸 넣을 수 없음

- 한국어 변수 사용가능하나 인코딩 이슈로 권장하지 않음

 

✅ 변수 보기 및 삭제

- ls() : 변수 보기

- rm(변수명) : 변수 삭제

- rm(list = ls()) : 변수 모두 삭제

 

 

2.4 함수

- 매개변수를 받아 정의된 내용을 실행하며, 결과 값을 리턴하는 장치

 

✅ 내장 함수

- 산술 함수 : min, max, sum, prod, factorial, abs

- 강제 형변환 함수 : as

vec <- c(T, F, FALSE)
vec2 <- as.numeric(vec)
vec3 <- as.logical(vec2)
vec4 <- as.character(vec3)

vec   # [OUT] TRUE FALSE FALSE
vec2  # [OUT] 1 0 0
vec3  # [OUT] TRUE FALSE FALSE
vec4  # [OUT] "TRUE"  "FALSE" "FALSE"


# 높은 우선 순위 → 낮은 우선 순위 형 변환
# character > numeric > logical
test <- c('char', '10', 'TRUE')
test_to_num <- as.numeric(test)
test_to_logic <- as.logical(test)

test_to_num    # [OUT] NA 10 NA
test_to_logic  # [OUT] NA NA TRUE

 

- 데이터 생성 함수 : seq, rnom, runif

# seq 함수 (from으로부터 by씩 증가하는 length개의 숫자로 이루어진 벡터 생성)
seq(length = 5, from = 3, by = 2) # [OUT] 3  5  7  9 11

# rnorm 함수 (평균이 mean, 분산이 sd인 정규분포를 따르는 n개의 숫자로 이루어진 벡터 생성)  
rnorm(n = 4, mean = 0, sd = 1)  # [OUT] -0.21253399 -0.03296793  0.07698710  0.48839667

# runif 함수 ([min, max] 범위 사이 n개의 난수로 이루어진 벡터 생성)
runif(n = 4, min = 1, max = 100)  # [OUT] 11.33962 14.06943 94.06348 14.83108

 

 

✅ 사용자 정의 함수

- 사용자가 직접 정의하여 만들어내는 함수

myFunc <- function(x) {
  return (2*x + 2)
}
a <- myFunc(2)
print(a)   # [OUT] 6
print(myFunc(3))   # [OUT] 8

 

 

2.5 패키지

- 유사한 기능을 하는 함수들의 모음

 

✅ 패키지 관리 함수

- install.packages('패키지 이름') : 패키지 설치

- library(help = 패키지 이름) : 패키지에 대한 정보 출력

- update.packages('패키지 이름') : 패키지를 최신 버전으로 업데이트 (패키지 이름 기재하지 않으면 모든 패키지 업데이트)

- remove.packages('패키지 이름') : 패키지 삭제

 

 

2.6 [실습] 고객의 은행 대출 상품 신청 현황 데이터

첫번째 표와 같이 데이터프레임(result)을 생성하고, 두번째 표와 같이 수정(result_new)하세요.

[수정사항]

1. 문자 데이터 수정은 stringr 패키지의 함수 사용할 것
2. job 컬럼의 “은퇴” 값은 “무직”으로 대체 할 것
3. marital 컬럼은 logical 값으로 관리 할 것 (“결혼” 값은 T로, 나머지 값은 모두 F로 관리)
4. 수정된 결과물은 result_new 변수에 할당 후 출력 할 것

https://archive.ics.uci.edu/ml/datasets/bank+marketing

 

# Age : numeric (Integer) / 수치형/범주형
# Job : character / 범주형
# Marital : character / 범주형
# Balance : numeric / 수치형
# Campaign : character / 범주형
# Y : logical / 범주형

# 1. 컬럼 별 변수 생성
age <- c(30, 33, 35, 30, 68, 33)
job <- c('무직', '서비스', '관리직', '관리직', '은퇴', '관리직')
marital <- c('결혼', '결혼', '미혼', '결혼', '사별', '결혼')
balance <- c(1787, 4789, 1350, 1476, 4189, 3935)
campaign <- c('휴대폰', '휴대폰', '휴대폰', 'Unknown', '유선전화', '휴대폰')
Y <- c(F, F, F, F, T, T)

# 2. 데이터프레임 생성한 것을 result 변수에 할당
result <- data.frame(age, job, marital, balance, campaign, Y)

# 3. 결과 출력
print(result)

# 4. 평균 나이, 평균 은행 잔고 출력
age_mean <- mean(age)
age_mean   # [OUT] 38.16667

balance_mean <- mean(balance)
balance_mean  # [OUT] 2921

# 5. 대출을 신청한 사람 수 계산
yToNum <- as.numeric(Y)  # [OUT] 0 0 0 0 1 1
yCount <- sum(yToNum)
print(yCount)  # [OUT] 2

# 6. 데이터값 수정
# 1) stringr 패키지 사용
install.packages('stringr')
library(stringr)

# 2) job 컬럼의 '은퇴' → '무직'으로 대체
job_new <- str_replace(job, '은퇴', '무직')
print(job_new)

# 3) marital 컬럼의 형을 logical로 변환 ('결혼' : T, 그 외 : F)
# '결혼'값을 'T'로 변환
marital_new <- str_replace(marital, '결혼', 'T')
print(marital_new)

# 문자형을 논리형으로 강제 형변환
marital_logical <- as.logical(marital_new)
print(marital_logical)

# NA 값을 F로 변환
marital_logical[is.na(marital_logical)] = FALSE
print(marital_logical)

# 4) 수정된 결과물은 result_new 변수에 할당 후 출력
result_new <- data.frame(age, job_new, marital_logical, balance, campaign, Y)
print(result_new)


3. 멘토링

R의 기본 기능을 다시 복습하고 다같이 간단한 예제를 풀어보는 시간을 가졌다.

 

3.1 벡터 만들기

- c() 함수: 해당하는 숫자 모두 기재 or 슬라이싱으로 기재

- seq(시작, 끝, 간격) 함수

- rep(벡터, 반복횟수) 함수

# 1. 벡터 만들기
# 1) 1부터 10까지의 숫자로 이루어진 벡터 만들기
c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
c(1:10)
seq(1, 10, 1)

# 2) 1, 2, 3, 50, 51, 52, 53, 54, 55로 이루어진 벡터 만들기
c(1, 2, 3, 50, 51, 52, 53, 54, 55)
c(1:3, 50:55)

# 3) 1부터 100까지 3간격의 숫자로 이루어진 벡터 만들기
seq(1, 100, 3)

# 4) 0.1부터 1까지 0.1 간격의 숫자로 이루어진 벡터 만들기
seq(0.1, 1, 0.1)

# 5) 1, 1, 1, 1, 1로 이루어진 벡터 만들기
rep(1, 5)

# 6) 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3
rep(1:3, 5)
rep(c(1, 2, 3), 5)

 

3.2 벡터 슬라이싱 / 인덱싱

- 변수명[첫 숫자 : 끝 숫자]

- 변수명[-인덱스] : 해당 인덱스를 제외하고 출력 

- 불린 인덱싱 : 출력하고자 하는 데이터의 인덱스에 T(TRUE) 기재

- 팬시 인덱싱 : 출력하고자 하는 데이터의 인덱스를 벡터로 기재

- names(변수명) <- 벡터

 

# 2. 벡터 인덱싱/슬라이싱
# 요일 별 결석자 데이터가 담긴 벡터 (absent)
absent <- c(3, 2, 0, 4, 1)

# 1) 인덱싱
# 월요일 결석자
absent[1] # [OUT] 3

# 수요일 제외 결석자
absent[-3]  # [OUT] 3 2 4 1

# 2) 슬라이싱
# 월화수 결석자
absent[1:3]  # [OUT] 3 2 0
absent[-4:-5]  # [OUT] 3 2 0
absent[-c(4:5)] # [OUT] 3 2 0
 
# 3) 불린 인덱싱
# 1, 3, 5번째 요소만 인덱싱
absent[c(T, F, T, F, T)]  # [OUT] 3 0 1

# 4) 팬시 인덱싱
# 1, 3, 5번째 요소만 인덱싱
absent[c(1, 3, 5)]   # [OUT] 3 0 1

# 5) 벡터 absent 각 요소에 'Mon', 'Tue', 'Wed', 'Thu', 'Fri' 이름 붙이기
names(absent) <- c('Mon', 'Tue', 'Wed', 'Thu', 'Fri')
absent
# [OUT]
# Mon Tue Wed Thu Fri 
# 3   2   0   4   1

# 6) 특정 요소 가져오기
absent['Mon']
absent[c('Mon', 'Wed')]

 

 

4. 회고

처음 R에 대해 배웠다. SQL, 파이썬과 비슷하긴 한데, 또 다른 문법과 함수들이 있어서 조금씩 헷갈렸다.

하지만 생각보다 파이썬보다 문법이 간단했다. 벡터, 리스트, 데이터프레임 등 다양한 데이터 자료를 간단한 명령어로 만들 수 있었다.

특히, R에서는 자료 구조가 중요해서 이에 대해 자세하게 배웠다. 다소 헷갈리긴 하지만 계속 공부하면 머릿속에 잘 입력이 될 듯하다.

R이 통계적인 분석을 할 때 유용하다고 했는데, 아직 R의 기본 기능과 문법을 익히는 중이라 와닿지는 않는다. 내일과 내일 모레에 R을 심층적으로 공부하면서 통계적인 부분을 다룰 수 있지 않을까 싶다.

R, SQL, 파이썬이 헷갈리지 않도록 잘 정리해두자.

728x90