Skip to main content

R 기초, 조건에 맞는 데이터 선택하기

R좋은게 소문이 났는지? 주위에서 R을 배우는 교수님과 동료 선생님들이 늘어나는 것 같다. 나는 R을 엄청 잘 쓴다고 말은 못하지만, 어쩌다 보니 R에서 통계량 계산만 하고, Excel로 돌아가 다시 데이터를 정리해서 import하는 불필요한 일은 피할 정도가 되었다. 가끔은 사용자 함수를 만들어서 복잡한 text mining도 하고 반복작업을 줄이기도 한다. (매번 잘 되지는 않는다. 하지만 반복작업을 줄이는 코드를 만드는 것이 재미있다.)

논문 작성을 위한 데이터 정리를 노가다 또는 삽질이라고 부르는 친구들도 있지만 나는 그나마 R로 해결되는 것들이라면 코딩하는(?) 재미로 할 만 하다. 오늘부터는 이따금 R 사용법을 안내하는 글을 올려보려고 한다. 가르치는 것은 두 번 배우는 것이라 했으니 배운 것을 꼭꼭 씹어먹고 소화시키기 위함이다. (오늘만 해도 이걸 올리느라 R markdown을 배웠다. ㅎㅎ)

첫번째로, 가장 필요하고 중요하다고 생각되는 data frame의 subsetting 에 대해 써본다.



잘못된 정보가 있으면 댓글로 알려주시면 감사하겠습니다.

의학 논문 작성을 위한 R 기초

1. Data frame의 subsetting

1.1. Data frame과 vector

의학 연구자들이 기본적으로 사용하는 데이터는 열과 행으로 이루어진 데이터스프레드시트이다. 엑셀 등으로 작업이 된 경우도 있고 csv파일로 정리된 경우도 있는데 어쨌든 대부분은 csv파일로 변환해서 R에서 불러오게 된다.
example <- read.csv("c:/R/R_document/mtcars.csv", header = TRUE) #파일 경로는 이렇게
example <- read.csv("c:\\R\\R_document\\mtcars.csv", header = TRUE) #또는 이렇게도 가능하다.
#example <- read.csv("c:\\R\\R_document\\mtcars.csv", header = TRUE) 이렇게 쓰면 안 된다.

데이터를 R으로 불러오면 내부에서 data frame 형식으로 존재하게 된다.
class(example)
## [1] "data.frame"

하지만 data frame 형식의 데이터를 다루기 위해서는 다른 형식의 데이터셋(vector, matrix, list)에 대한 기본 지식을 갖추는 것이 좋다. 우선 vector만 이해해도 충분하다.

우선 불러온 데이터를 살펴보자. 데이터의 10행만 출력해보겠다.
head(example, 10) #10이라는 숫자를 입력하지  않으면 기본적으로 6줄을 보여준다.
##     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## 7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## 8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## 9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## 10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4

여기서 첫번째 column만 따로 가져와보겠다. 여러가지 방법이 있다.
first_column_1 <- example$mpg #1
first_column_2 <- example["mpg"] #2
first_column_3 <- example[1] #3

세 가지 방법의 결과는 다르다. (1 ≠ 2 = 3) 결과물을 출력해보면
first_column_1
##  [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0
## [28] 30.4 15.8 19.7 15.0 21.4
class(first_column_1)
## [1] "numeric"
str(first_column_1) #구조를 보여준다.
##  num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...

첫 번째 방법은 example의 첫 column을 가져와서 (numeric) vector로 만든 것이다. Vector는 같은 형태(e.g. numeric, integer, charactor, factor, logical)의 데이터를 여러개 묶은 형태이다.
class(first_column_2)
## [1] "data.frame"
str(first_column_2)
## 'data.frame':    32 obs. of  1 variable:
##  $ mpg: num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
head(first_column_2, 3)
##    mpg
## 1 21.0
## 2 21.0
## 3 22.8

두 번째 방법은 data frame의 형태가 유지되어있다. Data frame이라 세로로 긴 여러행이라서 3줄만 출력하였다.

Vector의 특성에서 중요한 것은 logical vector로 부분집합을 가져올 수 있다는 것이다.
vector_1 <- c(15, 16, 17)
#c()는 벡터를 만드는 함수이다. 문자열 벡터는 따옴표 필요 c("a", "b")
vector_1[c(TRUE, FALSE, TRUE)] #1, 3번째 원소만 선택
## [1] 15 17
logical_1 <- c(TRUE, FALSE, TRUE) 
vector_1[logical_1] #이번엔 미리 만들어놓은 logical vector를 넣어서 선택해봤다.
## [1] 15 17

반대로 vector에 조건을 걸어 logical vector를 만들어낼 수 있는데 만들어낸 logical vector를 일종의 필터로 이용하여 다시 해당 조건의 원소를 추출할 수 있다.
logical_2 <- vector_1 > 15 #15보다 큰 원소는 TRUE로 그렇지 않으면 FALSE로 반환
logical_2
## [1] FALSE  TRUE  TRUE
vector_1[logical_2] #logical vector를 이용해서 해당 원소 추출
## [1] 16 17
vector_1[vector_1 > 15] #앞에서 한 것을 한 번에 쓰면
## [1] 16 17

1.2. Data frame의 subsetting - 기본

앞에서 불러온 data frame인 example의 특정 행과 열을 선택해보자.
example[1, 3] #1행 3열
## [1] 160
example[4, "disp"] #4행 disp열
## [1] 258
example[4, ] #4행
##    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
example[, "disp"] #disp열 = example$disp와 같다.
##  [1] 160.0 160.0 108.0 258.0 360.0 225.0 360.0 146.7 140.8 167.6 167.6 275.8 275.8 275.8 472.0 460.0 440.0  78.7  75.7  71.1 120.1 318.0 304.0
## [24] 350.0 400.0  79.0 120.3  95.1 351.0 145.0 301.0 121.0
example[5, c("mpg", "disp")] #5행, mpg와 disp열
##    mpg disp
## 5 18.7  360
example[5, c(1, 3)] #5행, 1과 3열
##    mpg disp
## 5 18.7  360
example[c(1:3), c(1:3)] #1-3행, 1-3열
##    mpg cyl disp
## 1 21.0   6  160
## 2 21.0   6  160
## 3 22.8   4  108
example[c(TRUE, FALSE), c(1:3)]
##     mpg cyl  disp
## 1  21.0   6 160.0
## 3  22.8   4 108.0
## 5  18.7   8 360.0
## 7  14.3   8 360.0
## 9  22.8   4 140.8
## 11 17.8   6 167.6
## 13 17.3   8 275.8
## 15 10.4   8 472.0
## 17 14.7   8 440.0
## 19 30.4   4  75.7
## 21 21.5   4 120.1
## 23 15.2   8 304.0
## 25 19.2   8 400.0
## 27 26.0   4 120.3
## 29 15.8   8 351.0
## 31 15.0   8 301.0
#c(TRUE, FALSE)는 전체 행 개수보다 적어서 이 두 값이 반복해서 대입되며 홀수행만 선택된다.
#행 개수에 맞는 logical vector를 넣어줄 수도 있다. (아래 응용편으로 이어지는 내용임.)

1.3. Data frame의 subsetting - 응용

앞에서 배운 것을 응용해보자. 특정 값을 기준으로 subsetting을 해보자. dataframe[logical vector, ]를 하게 되면 TRUE에 해당하는 행만 출력된다. logical vector를 만드는 법은 위에서 설명하였다.
selected <- example[example$mpg < 20, ] #mpg < 20인 행만 선택
head(selected)
##     mpg cyl  disp  hp drat   wt  qsec vs am gear carb
## 5  18.7   8 360.0 175 3.15 3.44 17.02  0  0    3    2
## 6  18.1   6 225.0 105 2.76 3.46 20.22  1  0    3    1
## 7  14.3   8 360.0 245 3.21 3.57 15.84  0  0    3    4
## 10 19.2   6 167.6 123 3.92 3.44 18.30  1  0    4    4
## 11 17.8   6 167.6 123 3.92 3.44 18.90  1  0    4    4
## 12 16.4   8 275.8 180 3.07 4.07 17.40  0  0    3    3

selected <- example[example$gear == 3, ] #gear = 3인 행만 선택
head(selected)
##     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## 7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## 12 16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## 13 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3

selected <- example[example$gear != 3, ] #gear = 3인 행만 제외
selected[order(selected$carb),] #carb값을 기준으로 오름차순으로 정렬
##     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## 18 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## 20 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## 26 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## 8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## 9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## 19 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## 27 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## 28 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## 32 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
## 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## 10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## 11 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## 29 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## 30 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## 31 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
selected[order(-selected$carb),] #carb값을 기준으로 내림차순 정렬
##     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## 31 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## 30 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## 10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## 11 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## 29 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## 8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## 9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## 19 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## 27 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## 28 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## 32 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
## 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## 18 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## 20 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## 26 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1

이상의 기능들을 이용하면 기본적인 데이터 subsetting은 가능하다고 본다.

Comments

Popular posts from this blog

잘못 발음하기 쉬운 의학 용어 영어 단어 모음 (계속 업데이트)

의학 용어 영단어들은 대개 다 영어라서 한글로 바꾸기도 어렵고, 우리말로 바꿔놓은 텍스트를 읽노라면 원서를 읽는 것보다 머리가 더 지끈거릴 때도 있다. 하지만 원서는 그저 눈으로 읽을 뿐이다. 결국 발음은 제각각 다들 개성넘치게 하고 수업시간에도 웬만해서는 제대로 된 발음을 배울 수가 없다. 그렇게 의대 본과 4년, 인턴과 레지던트 5년 합쳐 9년 동안 굳어진 잘못된 발음을 이후에도 계속 쓰는게 일반적이다. 이왕 하는 영어 공부 내 전공에도 접목시켜보자. 매번 마음속으로 갸우뚱하며 자신없이 발음했던 의학 용어들을 머릿속에 떠오르는 대로 검색해 목록을 만들었다. 앞으로 발음이 헷갈리는 다른 의학 용어가 생길 때마다 바로 사전을 찾아보든지 유튜브를 찾아보고 정리해놓을 예정이다. 작심삼일이 되지 않기를 바랄 뿐이다. (마지막 업데이트 2020. 5. 27.) 단어 / Pronunciation symbols (Merriam-Webster dictionary) Anatomy-related pulmonary /  ˈpu̇l-mə-ˌner-ē / ㅓ와ㅜ의 중간느낌? 퍼ㅜㄹ머네리 *Cambridge [ˈpʊl.mə.ner.i], Oxford [|pʌlməneri], Collins  [pʌlməneri] mediastinum / mē-dē-ə-ˈstī-nəm / 메디아스티넘 아니고 미디어스타이넘 endocrine / ˈen-də-krən  , -ˌkrīn, -ˌkrēn / 엔도크라인 아니고 엔도크런, 엔도크린 aorta /  ā-ˈȯr-tə / 아올타 아니고 에이올더 atrium / ˈā-trē-əm / 아트리움 아니고 에이트리엄 myocardium / mī-ə-ˈkär-dē-əm / 마이오카ㄹ디엄 branchial / ˈbraŋ-kē-əl / 브랜키-얼 bronchial / ˈbräŋ-kē-əl / 브란키-얼 bronchiole / ˈbräŋ-kē-ˌōl / 브란키-오울 azygos / (ˌ)ā...

Drinking culture in Korea: Honsul (drinking alone) / 한국의 음주 문화: 혼술

Honsul (혼술, drinking alone) is a combination of two words, honja (혼자, alone) and sul-masigi (술 마시기, drinking). It has become a trendy and widely used word to describe how people have been drifting away from drinking with company since the 2010s. This trend is generally thought of as driven by the growing number of people in their 20s and 30s who are living alone. '혼술'은 '혼자'와 '술 마시기'의 합성어입니다. 이 단어는 사람들이 무리지어 음주를 하는 것을 기피하는 현상을 나타내는 단어로 2010년대 이후 유행하여 널리 쓰이게 되었습니다. 혼자 사는 20대, 30대 인구가 늘어나면서 이들이 이러한 문화를 주도하는 것으로 알려져 있습니다. Honsul at home (only two days ago) Honsul as a counter-reaction to hoe-sik 혼술, 회식 문화에 대한 반작용 Drinking alone never used to be common in Korea. Many people who were born in the 1960s and 70s are heavily group oriented. They highly value group activities and like to do everything "together." Members of their groups aren't allowed to say "no" to group activities. As they are now in key positions of companies, the...

토익 공부 안 하고 한 번에 985점 받은 후기/평소 영어 실력 키우기

공인 영어 시험 성적이 필요하지도 않았는데 작년에 수험료 할인 기회가 있어서 토익 시험을 보았다. 공인 영어 시험은 약 8년만이었다. 토익 점수가 영어 실력과 비례한다고는 생각하지 않는다. 문제풀이 스킬에 의존해서 실제 실력에 비해 고득점을 받을 수도 있고, 점수만 높고 말하기가 전혀 안 되는 사람들도 있다. 하지만 반대로 평소 영어 실력이 좋다면 학원 도움 없이 어렵지 않게 고득점을 받을 수 있을 수 있을 것이라 생각한다. 나는 1년 정도 일상에서 영어와 친해지려고 노력했고 내 실력 변화가 궁금했다. 내 평소 실력을 확인하고 싶어서 문제 유형 확인을 위한 모의고사 1회만 풀어보고 토익 시험에 응시했다. (파트별 문제집이나 학원의 도움을 받지 않았다.) 나는 30대 중반의 직장인이다. 직장에서는 그닥 영어를 쓸 일이 없다. 이제까지 해외여행을 제외하고 외국에 살아 본 적이 없다. 최근 10년간은 영어 학원에 다닌 적이 없다. +고등학교 시절 1학년때 한 8개월, 3학년 때 2개월 정도 영어 학원에 다녔다. 과외는 받아본 적이 없다. 대학생 때(텝스 990이 만점이던 시절) 텝스 공부를 혼자서 해본 적이있다. 신입생 때 교내 모의 토익을 한 번, 8년전에 취업 서류 제출때문에 공인 토익 시험을 한 번 봤다. 다만, 시험을 보기 전에 1년 정도는 영어와 친해지려고 노력했다. 영어를 시험 과목이나 자격증이 필요한 분야보다는 그저 언어로 생각하며 지냈다. 특별한 목표 설정 없이 그저 일상에서 영어를 많이 사용하려고 했는데 자세한 이야기는 뒤에서 하려고 한다. 985 점이 나왔다. 세상에, 나도 놀랐다. Listening part는 사실 안 들리는 부분은 거의 없었다. 다만 내가 영어 시험이란걸 본 지가 오래 되어서 그런지 '와 요새는 보기가 이런식으로 나와?' 하다가 다음 문제를 못 듣고 당황해서 찍은게 몇 개 있었는데 거기서 틀린 것 같다. 아직 운전하며 우리말 라디오 방송 듣듯이 편하...