# [R] 데이터 개요

## 데이터

---

### 데이터 세트 (data set)

![Image](https://upload.cafenono.com/image/slashpagePost/20250128/005714_PNEkY5iFgOt8H2447L?q=80&s=1280x180&t=outside&f=webp)

- **테이블(table)**:  **행(row)**와 **열(column)**으로 이루어진 nxm 형태의 **데이터 세트(data set)**

- 행: 데이터의 **관측치(observation)**

- 열: **변수(variable)**

- 행과 열에 들어가 있는 데이터는 **값(value)**

### 데이터 구조 간 관계 및 데이터 유형

**데이터 구조**

- R에는 **벡터(vector), 행렬(matrix), 배열(array), 리스트(list), 데이터 프레임(dataframe), 팩터(factor)**가 존재

- **벡터(vector)**: 한 가지 데이터 유형으로 구성된 1차원 구조의 데이터

- **행렬(matrix)**: 한 가지 데이터 유형으로 구성된 2차원 구조의 데이터

- **배열(array)**: 행렬을 n차원으로 확대

- **리스트(list)**: 숫자형 벡터, 문자형 벡터 등 여러 데이터 유형이 포함된 1차원 구조의 데이터

- **데이터 프레임(dataframe)**: 리스트를 2차원으로 확대한 구조의 데이터

**데이터 자료형**

- **숫자형(number)**: 숫자로만 이루어진 데이터

- **문자형(character)**: 문자로만 이루어진 데이터

- **논리형(logical)**: TRUE / FALSE 로 이루어진 데이터

| **자료형** | **사용 예** | **비고** |
| --- | --- | --- |
| 숫자형 | 1, 2, -4, 12.8 | 정수, 실수 모두 가능 |
| 문자형 | ‘Tom’, ‘Jane’ | 작은따옴표나 큰따옴표로 묶어서 표현 |
| 논리형 | TRUE, FALSE | T, F로 줄여서 사용하는 것도 가능 |
| 특수값 | NULL NA NaN Inf, -Inf | 정의되어 있지않음을 의미, 자료형도 없고 길이도 0 결측값(missing value) 수학적으로 정의가 불가능한 값 (sqrt(-3)) 양의 무한대(Inf), 음의 무한대(-Inf) |

**데이터에 저장되어 있는 값들에 따라**

- **범주형**: 분류의 의미를 갖는 값들

- **수치형**: 값들이 크기를 가지며 산술 연산이 가능

**데이터 분류**

- **데이터 유형**

    - **단일형**: 숫자형, 문자형과 같이 **한 가지 데이터 유형**으로만 구성

        - 벡터, 행렬, 배열

    - **다중형**: 숫자 데이터, 문자데이터 등 **여러 데이터 유형**으로 구성

        - 리스트, 데이터프레임

- **차원**

    - **1차원 데이터**: 직선 위에 값이 나열되어 있으므로 기준점을 중심으로 얼마나 떨어져 있는 지만 알면 된다.

    - **2차원 데이터**: 1차원 데이터의 모임, 2가지 정보를 알아야 원하는 값을 찾을 수 있다.

    - **n차원 데이터**: n가지 정보를 알아야 원하는 값을 찾을 수 있다.

|  | **1차원** | **2차원** | **n차원** |
| --- | --- | --- | --- |
| **단일형** | 벡터 | 행렬 | 배열 |
| **다중형** | 리스트 | 데이터 프레임 |  |

## 벡터(vector)

---

- R에서 제공하는 여러 개의 값을 한꺼번에 저장하는 기능 (같은 자료형만 가능)

- 1차원 배열(array)라고도 한다.

- 파이썬의 1차원 리스트와 유사

- 수학 벡터와 성질이 같기 때문에 벡터라고 부른다.

### **벡터 만들기**

- 하나의 벡터에는 동일한 자료형(data type) 값이 저장되어야 한다.

**c()**

- c는 combine의 첫 자를 따온 것

- 여러 개의 값을 하나로 묶어주는 역할

- 하나의 벡터에 여러 개의 값이 저장된다.

```javascript
score <- c(68, 95, 83, 76, 90, 80, 85, 91, 82, 70)
mean(score)
```

```javascript
score.1 <- 68; score.2 <- 95; score.3 <- 83; score.4 <- 76; score.5 <- 90
score.6 <- 80; score.7 <- 85; score.8 <- 91; score.9 <- 82; score.10 <- 70
total <- score.1 + score.2 + score.3 + score.4 + score.5 + score.6 + score.7 + score.8 + score.9 + score.10
avg <- total / 10
avg
```

**콜론(:)**

- 콜론(:)을 이용하면 연속된 정수로 이루어진 벡터를 만들 수 있다.

```javascript
v1 <- 50:90 # 콜론으로 정수 연속된 벡터를 만들 수 있음
v1

v2 <- c(1, 2, 5, 50:90) # c내부에서 콜론 사용 가능
v2
```

**seq(시작, 종료, 간격)**

- 시작값에서 출발하여 일정 간격으로 정수값, 소수값 생성하다 종료값이 되면 생성 중지

- 일정한 간격의 숫자로 이루어진 벡터를 만들 수 있다.

```javascript
v3 <- seq(1, 101, 3) # 시작, 종료, 간격
v3

v4 <- seq(0.1, 1.0, 0.1)
v4
```

**rep(반복 대상값, times=반복횟수)**

- 반복 대상 값은 하나일 수도 있고 여러 개의 값일 수도 있다.

- rep()으로 반복된 숫자로 이루어진 벡터를 반들 수 있다.

```javascript
v5 <- rep(1, times=5) # 1을 5번 반복
v5

v6 <- rep(1:5, times=3) # 1, 2, 3, 4, 5를 3번 반복
v6

v7 <- rep(c(1, 5, 9), times=3) # 1, 5, 9를 3번 반복
v7

v8 <- rep(c('a', 'b', 'c'), each = 3) # 각 3번 반복
v8
[1] "a" "a" "a" "b" "b" "b" "c" "c" "c"
```

### names()

- 벡터 이름 지정

- names()를 사용하여 각 벡터 요소에 이름을 붙일 수 있다.

```javascript
> absent <- c(8, 2, 0, 4, 1) 
> absent
[1] 8 2 0 4 1
> names(absent)
NULL
> names(absent) <- c('Mon', 'Tue', 'Wed', 'Thu', 'Fri') # 값들의 이름을 입력
> absent
Mon Tue Wed Thu Fri 
  8   2   0   4   1 
> names(absent)
[1] "Mon" "Tue" "Wed" "Thu" "Fri"
```

### **원소값 확인**

- 인덱스(index): 벡터에 저장된 각각의 값들을 구별하기 위하여 앞쪽의 값부터 순서를 부여

- 특정 위치에 저장된 값들을 하나 또는 여러 개 추출하여 계산에 이용 가능

**배열에서 일부 요소만 불러올 수 있음**

```javascript
> d <- c(1, 4, 3, 7, 8)
> d[c(1, 3, 5)]
[1] 1 3 8
> d[1:3]
[1] 1 4 3
> d[seq(1, 5, 2)]
[1] 1 3 8
> d[-2]
[1] 1 3 7 8
> d[-c(3:5)]
[1] 1 4
```

**R은 이름, 인덱스를 모두 이용하여 값을 추출할 수 있다.**

```javascript
> sales <- c(640, 720, 680, 540)
> names(sales) <- c('M1', 'M2', 'M3', 'M4')
> sales
 M1  M2  M3  M4 
640 720 680 540 
> sales[1]
 M1 
640 
> sales['M2']
 M2 
720 
> sales[c('M1', 'M4')]
 M1  M4 
640 540
```

### **벡터에 저장된 원소값 변경**

- 배열에 새로운 값을 넣으면 배열의 값이 모두 바뀐다.

```javascript
> v1 <- c(1, 5, 7, 8, 9)
> v1
[1] 1 5 7 8 9
> v1[2] <- 3
> v1[c(1, 5)] <- c(10, 20)
> v1
[1] 10  3  7  8 20
> v1 <- c(100, 200, 300)
```

### 벡터 연산

**벡터 산술 연산**

- 벡터 안에 포함된 값들 하나하나에 대한 연산을 바뀌어 실행

```javascript
> d <- c(1, 4, 3, 7, 8)
> 2*d
[1]  2  8  6 14 16
> d-5
[1] -4 -1 -2  2  3
> 3*d + 4
[1]  7 16 13 25 28
```

**벡터와 벡터 연산**

- 벡터 내 대응하는 원소끼리 연산을 진행

```javascript
> x <- c(1, 2, 3, 4)
> y <- c(5, 6, 7, 8)
> x + y
[1]  6  8 10 12
> x * y
[1]  5 12 21 32
> z <- x + y
> z
[1]  6  8 10 12
```

1. 두 벡터의 길이 가 같아야 한다.

2. 두 벡터에 포함된 값의 종류가 같아야 한다.

- c()로 두 벡터를 결합할 수 있다.

```javascript
> m <- c(x, y)
> m
[1] 1 2 3 4 5 6 7 8
> n <- c(y, x)
> n
[1] 5 6 7 8 1 2 3 4
> p <- c(x, y, 90, 100)
> p
 [1]   1   2   3   4   5   6   7   8  90 100
```

**벡터에 적용 가능한 함수들**

| **함수명** | **설명** |
| --- | --- |
| sum() | 벡터에 저장된 값들의 합 |
| mean() | 벡터에 저장된 값들의 평균 |
| median() | 벡터에 저장된 값들의 중앙값 |
| max(), min() | 벡터에 저장된 값들의 최댓값, 최솟값 |
| var() | 벡터에 저장된 값들의 분산 |
| sd() | 벡터에 저장된 값들의 표준편차 |
| sort() | 벡터에 저장된 값들의 정렬(오름차순이 기본) |
| range() | 벡터에 저장된 값들의 범위(최솟값, 최댓값) |
| length() | 벡터에 저장된 값들의 개수 (벡터의 길이) |

```javascript
> d <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
> sum(d)
[1] 55
> sum(2*d)
[1] 110
> length(d)
[1] 10
> mean(d[1:5])
[1] 3
> max(d)
[1] 10
> min(d)
[1] 1
> sort(d)
 [1]  1  2  3  4  5  6  7  8  9 10
> sort(d, decreasing=FALSE)
 [1]  1  2  3  4  5  6  7  8  9 10
> sort(d, decreasing=TRUE)
 [1] 10  9  8  7  6  5  4  3  2  1
> 
> v1 <- median(d)
> v1
[1] 5.5
> v2 <- sum(d)/length(d)
> v2
[1] 5.5
```

**논리 연산자**

| **함수명** | **사용 예** | **설명** |
| --- | --- | --- |
| < | A < B | B가 A보다 크면 TRUE |
| <= | A <= B | B가 A보다 크거나 같으면 TRUE |
| > | A > B | A가 B보다 크면 TRUE |
| >= | A >= B | A가 B보다 크거나 같으면 TRUE |
| == | A == B | A와 B가 같으면 TRUE |
| != | A != B | A와 B가 같으면 TRUE |
| | | A | B | A 또는 B 어느 한쪽이라도 TRUE이면 TRUE |
| & | A & B | A와 B모두 TRUE일 때만 TRUE |

```javascript
# 코드 4-6
> d <- 1:9
> d >= 5
[1] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE
[8]  TRUE  TRUE
> d[d>5]
[1] 6 7 8 9
> sum(d>5)
[1] 4
> sum(d[d>5])
[1] 30
> d==5
[1] FALSE FALSE FALSE FALSE  TRUE FALSE FALSE
[8] FALSE FALSE
> 
> condi <- d > 5 & d < 8
> d[condi]
[1] 6 7
```

## 팩터 factor

---

- 문자형 데이터가 저장되는 벡터의 일종

- 저장되는 문자값들이 어떤 종류를 나타내는 값일 때 사용

- **factor()** 함수를 이용해 벡터를 변환하여 만든다.

```javascript
bt <- c('A', 'B', 'B', 'O', 'AB', 'A') # 문자형 벡터 bt정의
bt.new <- factor(bt)                   # 팩터 bt.new 정의
bt                                     # 벡터 bt의 내용 출력
bt.new                                 # 벡터 bt.new의 내용 출력
bt[5]                                  # 벡터 bt의 5번째 값 출력
levels(bt.new)                         # 팩터에 저장된 값의 종류를 출력
as.integer(bt.new)                     # 팩터의 문자값을 숫자로 바꾸어 출력
bt.new[7] <- 'B'                       # 팩터의 bt.new의 7번째에 'B'저장
bt.new[8] <- 'C'                       # 팩터의 bt.new의 8번째에 'C'저장
bt.new                                 # 팩터 bt.new의 내용 출
```

- levels() 함수를 통해 출력된 문자값들의 순서가 변환될 숫자가 된다.

## 리스트 list

---

- 자료형이 다른 값들을 한곳에 저장하고 다룰 수 있도록 해주는 수단

- 여러 자료형이 섞여 있기 때문에 리스트에 저장해야함

```javascript
h.list <- c('balling', 'tennis', 'ski') # 취미를 벡터에 저장
person <- list(name='Tom', age=25, student=TRUE, hobby=h.list) # 리스트 생성
person      # 리스트에 저장된 내용 모두 출력
person[[1]] # 리스트의 첫 번째 값 출력
person$name # 리스트에서 값의 이름이 name인 값을 출력
person[[4]] # 리스트의 네 번째 값을 출력
```

## 매트릭스

---

- 모든 셀(cell)에 저장되는 값은 동일한 종류

- 보통 숫자로만 구성된 2차원 자료 저장, 처리

**매트릭스 생성**

```javascript
# 매트릭스 생성
x <- 1:4
y <- 5:8
z <- matrix(1:20, nrow=4, ncol=5, byrow=T)

m1 <- cbind(x, y)
m2 <- rbind(x, y)
```

- nrow: 행 개수

- ncol: 열 개수

- byrow: 행 방향으로 채우기

- cbind: 열 방향으로 결합

- rbind: 행 방향으로 결합

**매트릭스에서 값 추출**

```javascript
# 매트릭스 값 추출
z[행,열] # 매트리스 값 추출
z[1, c(1, 2, 4)] # 1행의 값 중 1, 2, 4열
z[1, 1:4] # 1행의 값 중 1, 2, 3, 4열
```

```javascript
# 행과 열에 이름 붙이기
score <- matrix(c(90, 85, 69, 78, 85, 96, 49, 95,90, 80, 70, 60), nrow=4)
rownames(score) <- c('John', 'Tom', 'Mark', 'Jane')
colnames(score) <- c('English', 'Math', 'Science')
```

- rownames(): 행 이름을 붙이거나 출력

- colnames(): 열 이름을 붙이거나 출력

### 데이터프레임 dataframe

---

- 2차원 형태의 데이터를 저장하고 분석하는데 사용되는 자료구조

```javascript
# 데이터프레임 만들기
city <- c("Seoul", "Tokyo", "Washington")
rank <- c(1, 3, 2)
city.info <- data.frame(city, rank)
city.info
```

**iris 데이터셋**

- 150그루의 붓꽃에 대해 4개 분야의 측정 데이터와 품종 정보 결합

```javascript
# iris 데이터셋
iris

iris[, c(1:2)]
iris[, c(1, 3, 5)]
iris[, c("Sepal.Length", "Species")]
iris[1:5, ]
iris[1:5 c(1, 3)]
```

| **열 이름** | **의미** | **자료형** |
| --- | --- | --- |
| Sepal.Length | 꽃받침의 길이 | 숫자형 |
| Sepal.Width | 꽃받침의 폭 | 숫자형 |
| Petal.Length | 꽃잎의 길이 | 숫자형 |
| Petal.Width | 꽃잎의 폭 | 숫자형 |
| Species | 붓꽃의 품종 | 문자형(팩터) |

## 매트릭스와 데이터프레임 다루기

---

### **데이터셋의 기본 정보 알아보기**

```javascript
dim(iris)                # 행과 열 개수
nrow(iris)               # 행 개수
ncol(iris)               # 열 개수
colnames(iris)           # 열 이름 (names()와 동일)
head(iris)               # 데이터셋의 앞부분 일부
tail(iris)               # 데이터셋의 뒷부분
str(iris)                # 데이터셋 요약 정보
iris[, 5]                # 품종 데이터 보기
levels(iris[, 5])        # 품종 종류 (중복제거)
table(iris[, "Species"]) # 품종 종류별 행의 개수
```

### **매트릭스와 데이터프레임에 함수 적용**

```javascript
# 합계, 평균
colSums(iris, [, -5])  # 열별 합계
colMeans(iris, [, -5]) # 열별 평균
rowSums(iris, [, -5])  # 행별 합계
rowMeans(iris, [, -5]) # 행별 평균

# 행렬전환 (전치행렬)
t(z)

# 조건에 맞는 행, 열 값 추출
IR.1 <- subset(iris, Species == 'setosa')
IR.2 <- subset(iris, Sepal.Length > 5.0 & Speal.Width > 4.0)

# 산술연산
a + b
2 * a
```

### **매트릭스와 데이터프레임의 자료구조 확인과 변환**

```javascript
class(iris)              # iris 데이터셋의 자료구조 확인
class(state.x77)         # state.x77 데이터셋의 자료구조 확인
is.matrix(iris)          # 데이터셋이 매트릭스인지 확인하는 함수
is.data.frame(iris)      # 데이터셋이 데이터프레임인지 확인하는 함수
is.matrix(state.x77)
is.data.frame(state.x77)

# 매트릭스 -> 데이터프레임
st <- data.frame(state.x77)

# 데이터프레임 -> 매트릭스
iris.m <- as.matrix(iris[, 1:4])
```

### **데이터프레임 열 추출**

```javascript
# 데이터프레임, 매트릭스 모두 가능
iris[, "Species"]
iris[, 5]

# 데이터프레임만 가능
iris["Species"]
iris[5]
iris$Species
```

## 데이터 입출력

---

**R에서의 입력과 출력**

- R 프로그램은 분석 대상이 되는 데이터를 입력한 후 입력된 데이터를 분석하여 필요한 정보를 얻는 것이 일반적

```javascript
# 데이터 입력하고 입력된 데이터 내용 확인
age <- c(28, 17, 35, 46, 23, 67, 30, 50)
age

# 가장 젊은 사람과 가장 나이든 사람의 나이 데이터를 출력
young <- min(age)
old <- max(age)

# 처리 결과 출력
cat('가장 젋은 사람의 나이는 ', young, '이고, ', 
        '가장 나이든 사람의 나이는 ', old, '입니다. \n')
```

**화면에서 데이터 입력받기**

```javascript
install.packages('svDialogs')       # 패키지 설치
library(svDialogs)
user.input <- dlgInput('Input income')$res
user.input
income <- as.numeric(user.input)    # 문자열을 숫자로
income
tax <- income * 0.05                # 세금 계산
cat('세금: ', tax)
```

**print() 함수와 cat() 함수**

- 화면에서 프로그램의 처리 결과를 확인하는 가장 간단한 방법

| **함수** | **사용상의 특징** |
| --- | --- |
| **print()** | - 하나의 값을 출력할 때 - 데이터프레임과 같은 2차원 자료구조를 출력할 때 - 출력 후 자동 줄바꿈 |
| **cat()** | - 여러 개의 값을 연결해서 출력할 때 - (벡터는 출력되나 2차원 자료구조는 출력되지 않음) - 출력 후 줄바꿈을 하려면 ‘\n’ 필요 |

```javascript
x <- 26
y <- '입니다'
z <- c(10, 20, 30, 40)
print(x)            # 하나의 값 출력
print(y)            # 하나의 값 출력
print(z)            # 벡터 출력 
print(iris[1:5, ])  # 데이터프레임 출력
print(x, y)         # 두 개의 값 출려 (에러 발생)
```

```javascript
x <- 26
y <- '입니다'
z <- c(10, 20, 30, 40)
cat(x, '\n')         # 하나의 값 출력
cat(y, '\n')         # 하나의 값 출력
cat(z, '\n')         # 벡터 출력
cat(x, y, '\n') # 두 값을 연결하여 출력
cat(iris[1:5], '\n') # 데이터프레임 출력 (에러 발생)
```

### 데이터 읽기/쓰기

**작업폴더**

- 자신이 읽거나 쓰고자 하는 파일이 위치하는 폴더

- R에서 어떤 파일을 읽으려면 그 파일이 위치한 폴더의 경로와 함께 파일 이름을 지정

```javascript
getwd()
setwd('C:/Rworks')
getwd()
```

**csv 파일 읽기와 쓰기**

- R에서 데이터 분석을 위해 가장 많이 사용하는 파일 형태는 .csv 파일

```javascript
setwd('C:/Rworks')                          # 작업 폴더 지정
air <- read.csv('airquality.csv', header=T) # .csv 파일 읽기 
head(air)
class(air)                                  # air의 자료구조 확인

```

```javascript
setwd('C:/Rworks')    # 작업 폴더 지정
# setosa 품종 데이터만 추출
my.iris <- subset(iris, Species=='setosa')
# .csv 파일에 저장하기
write.csv(my.iris, 'my_iris.csv', row.names=F)
```

```javascript
install.packages('xlsx')  # 패키지 설치하기
library(xlsx)             # 패키지 불러오기

# .xlsx 파일 읽기
air <- read.xlsx('C:/Rworks/airquality.xlsx', header=T, sheetIndex=1) 
head(air)
```

```javascript
library(xlsx) # 패키지 불러오기
my.iris <- subset(iris, Species=='setosa')      # setosa 품종 데이터만 추출
write.xlsx(my.iris, 'my_iris.xlx', row.names=F) # 파일에 저장하기
```

### 데이터 입출력에서 알아야 할 내용

**실행 결과를 파일로 출력하기**

```javascript
setwd('C:/Rworks')            # 작업 폴더 지정
print('Begin work')           # 화면으로 출력
a <- 10; b <- 20
sink('result.txt', append=T)  # 파일로 출력 시작
cat('a+b = ', a+b, '\n')
sink()                         # 파일로 출력 정지
cat('hello world \n')          # 화면으로 출력
sink('result.txt', append=T)   # 파일로 출력 시작
cat('a*b=', a*b, '\n')
sink()                         # 파일로 출력 정지
print('End work')              # 화면으로 출력
```

**탭이나 공백으로 분리된 파일 읽기**

```javascript
setwd('C:/Rworks')                                     # 작업 폴더 지정
air <- read.table('airquality.txt', header=T, sep=' ') # 파일 읽기
head(air)                                              # 내용 확인
```

For the site tree, see the [root Markdown](https://slashpage.com/yerim-devnote.md).
