R) 전처리 - Filtering-02

R) 전처리 - Filtering-02

R에서 데이터프레임 객체에서 원하는 변수를 솎아내는 방법을 간단한 코드부터 고급 응용까지 알아본다.

※ 본 내용은 패널데이터 샘플인 panel_data_sample.csv 파일을 기반으로 진행한다.
panel_data_sample.csv 다운받기 [클릭]

우선 데이터를 읽어보면 다음과 같다.

1
2
df = read.csv("panel_data_sample.csv")
head(df, 2)

panel_data_sample.csv 파일
변수 개수가 매우 많다. 다음의 코드로 확인해보면 114개라는 것을 알 수 있다.

1
2
ncol(df)
[1] 114

이렇게 변수가 많은 경우 내가 원하는 변수를 어떻게하면 잘 골라낼 수 있을 것인가? 이제 각 난이도별 코드로 알아보자.

기본

“job” 으로 시작하는 변수를 골라낸다고 해보자. 전치행렬 함수 t()를 응용해서 “job”으로 시작하는 변수의 번호를 확인하는 코드는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
head(t(t(colnames(df))), 20)
## [,1]
## [1,] "pid"
## [2,] "Include"
## [3,] "Include_pid"
## [4,] "Include_SUB"
## [5,] "age_18th"
## [6,] "gender_18th"
## [7,] "marriage_18th"
## [8,] "religion_18th"
## [9,] "location_18th"
## [10,] "weekly_workhour_18th"
## [11,] "edu_scale_18th"
## [12,] "monthly_earning_18th"
## [13,] "overall_workplacesat"
## [14,] "overall_jobsat"
## [15,] "job_sat_1_re"
## [16,] "job_sat_2_re"
## [17,] "job_sat_3_re"
## [18,] "job_sat_4_re"
## [19,] "job_sat_5_re"
## [20,] "JSI"

15부터 19에 위치해있다. 이렇게 변수가 몇 개 되지 않고 눈으로 충분히 확인 가능한 경우는 다음과 같이 작성할 수 있다.

1
2
3
4
5
6
df_job = df[, c(15, 16, 17, 18, 19)] # 1
df_job = df[, 15:19] # 2
head(df_job, 2)
## job_sat_1_re job_sat_2_re job_sat_3_re job_sat_4_re job_sat_5_re
## 1 4 4 4 4 4
## 2 4 5 5 5 5

1번 코드는 변수의 번호가 연속이 아닐 때 사용할 수 있는 방법이지만, 지금은 연속해서 위치해있는 상황이기 때문에 2번 코드와 같이 간략하게 쓸 수 있다. 가끔 2번 코드를 df_job = df[, c(15:19)]이렇게 쓰는 경우가 있는데 여기서 함수 c()는 전혀 필요가 없다.

추가로 피해야할 문법이 있다. 다음과 같이 데이터프레임 객체를 필터링 하는데 대괄호 사이에 쉼표를 적지 않고 마치 list나 1차원 벡터를 다루듯 쓰는 것을 피해야 한다.

1
2
3
4
5
df_job = df[15:19]
head(df_job, 2)
## job_sat_1_re job_sat_2_re job_sat_3_re job_sat_4_re job_sat_5_re
## 1 4 4 4 4 4
## 2 4 5 5 5 5

이 문법은 R버전이 낮은 경우 에러를 유발하며 코드만 읽었을 때 df 객체가 데이터프레임이 아닌 것 처럼 보이기 때문에 에러가 발생하지 않더라도 쓰지 않는 것이 좋다.

물론 이렇게 무식하게 뽑아내는 것도 방법이다. 변수 개수가 아주 많은 경우에는 지옥문이 열리겠지만 이렇게 변수 개수가 10개 이하라면 무식한게 아니라 코드 가독성을 충분히 고려한 방법이라거나 변수의 위치가 바뀌어도 코드가 잘 동작하도록 좀 더 강인(robust)하게 작성된 코드라고 할 수 있겠다.

1
2
3
4
5
6
df_job = df[, c("job_sat_1_re", "job_sat_2_re",
"job_sat_3_re", "job_sat_4_re", "job_sat_5_re")]
head(df_job, 2)
## job_sat_1_re job_sat_2_re job_sat_3_re job_sat_4_re job_sat_5_re
## 1 4 4 4 4 4
## 2 4 5 5 5 5

중급

dplyr 패키지 기반의 문법을 작성하면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
library("dplyr")
df %>% select(c(15, 16, 17, 18, 19)) -> df_job # 1
df %>% select(15:19) -> df_job # 2
df %>% select(c("job_sat_1_re", "job_sat_2_re",
"job_sat_3_re", "job_sat_4_re",
"job_sat_5_re")) -> df_job # 3
df %>% select(job_sat_1_re:job_sat_5_re) -> df_job # 4
df_job %>% head(2)
## job_sat_1_re job_sat_2_re job_sat_3_re job_sat_4_re job_sat_5_re
## 1 4 4 4 4 4
## 2 4 5 5 5 5

1~3번 코드는 기본 문법과 다를바가 없는데 4번의 경우 select() 함수의 독특한 문법으로 연속된 변수를 보다 편리하게 지정할 때 사용할 수 있다.

개인적으로 전혀 좋아하지는 않지만 for 반복문이 아직 익숙하지 않은 사람들은 다음의 예제가 조금이나마 도움이 되지 않을까 싶다. 다음 코드는 df 객체의 변수명의 첫 번째 글자부터 세 번째 글자까지 뽑아서 “job”이라는 값과 같다면 col_names 객체에 집어넣는 방식으로 구성된 반복문이다.

1
2
3
4
5
6
7
8
9
10
11
col_names = c()
for(col_name in colnames(df)){
if(substr(col_name, start = 1, stop = 3) == "job"){
col_names = c(col_names, col_name)
}
}
df_job = df[, col_names]
head(df_job, 2)
## job_sat_1_re job_sat_2_re job_sat_3_re job_sat_4_re job_sat_5_re
## 1 4 4 4 4 4
## 2 4 5 5 5 5

위 코드의 간소화 버전은 다음과 같다. row 필터링도 그렇지만 column 필터링 또한 TRUEFALSE같은 논리값이 입력으로 들어오면 TRUE의 위치에 해당하는 변수만 추출할 수 있기에 다음과 같은 코드가 동작한다.

1
2
3
4
5
df_job = df[, substr(colnames(df), start = 1, stop = 3) == "job"]
head(df_job, 2)
## job_sat_1_re job_sat_2_re job_sat_3_re job_sat_4_re job_sat_5_re
## 1 4 4 4 4 4
## 2 4 5 5 5 5

고급

이전까지 눈으로 직접 확인하고 변수를 솎아냈지만 처음에 고민한 “job” 으로 시작하는 변수 를 그대로 코드에 적용하려면 다음과 같다.

1
2
3
4
5
6
7
8
df_job = df[, grep(pattern = "^job", colnames(df))] # 1
df_job = df[, grep(pattern = "^job", colnames(df), value = TRUE)] # 2
df_job = df[, grepl(pattern = "^job", colnames(df))] # 3
df %>% select(grep(pattern = "^job", colnames(df))) -> df_job # 4
head(df_job, 2)
## job_sat_1_re job_sat_2_re job_sat_3_re job_sat_4_re job_sat_5_re
## 1 4 4 4 4 4
## 2 4 5 5 5 5

grep()grepl() 함수는 둘 다 문자열의 패턴을 확인하고 그 것의 위치나 값 그리고 논리값을 반환하는 함수이다. 보통 필터링이라고 하면 row 부분만 해서 데이터프레임의 경우 대괄호 내부의 쉼표 앞에만 필터링 코드를 작성하는데 이렇게 변수명이 많은 경우는 쉼표 뒤에 이렇게 코드를 작성한다. 아무튼 grep() 함수의 pattern 인자에 입력된 “^job” 이라는 값은 “job”이라는 글자로 시작하는 이라는 규칙이다. 보다 다양한 규칙 적용은 R의 정규표현식(regular expression)을 활용하면 된다. 참고로 “re” 라는 문자로 끝나는 변수만 뽑고 싶다면 “^job” 대신 “re$” 라고 적어주면 된다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×