본문 바로가기

R/R을 이용한 데이터 처리&분석 실무

데이터 분리 및 병합

반응형

이 절에서는 주어진 데이터를 조건에 따라 분리하는 split(), subset() 함수 그리고 분리되어 있는 데이터를 공통된 값에 따라 병합하는 merge() 함수에 대해서 설명한다. 데이터를 분리하는 함수를 사용하면 조건에 만족하는 데이터를 미리 선택할 수 있어 이어지는 처리를 쉽게 할 수 있다. 또, 분리된 데이터는 merge()로 재병합할 수 있다. 다음에 이들 함수의 특징을 요약했다.

함수 특징
split() 주어진 조건에 따라 데이터를 분리한다.
subset() 주어진 조건을 만족하는 데이터를 선택한다.
merge() 데이터를 공통된 값에 기준해 병합한다.

 

split()

split()은 조건에 따라 데이터를 분리하는데 사용한다ㅣ.

 

-split : 주어진 기준에 따라 데이터를 분리한다.

split(

   x,    #분리할 벡터 또는 데이터 프레임

   f     #분리할 기준을 저장한 벡터

)

 

다음은 iris 데이터를 iris$Species에 따라 분리하고 결과를 리스트에 저장하는 예다.

>split(iris, iris$Species)
$setosa
     Sepal.Length   Sepal.Width   Petal.Length   Petal.Width    Species
1       5.1                 3.5             1.4                0.2            setosa
2       4.9                 3.0             1.4                0.2            setosa
...

$versicolor
      Sepal.Length   Sepal.Width   Petal.Length   Petal.Width    Species
51     7.0                 3.2             4.7                  1.4          versicolor
52     6.4                 3.2             4.5                  1.5          versicolor
...

$virginica
      Sepal.Length   Sepal.Width   Petal.Length   Petal.Width    Species
101     6.3              3.3              6.0                  2.5          virginica
102     5.8              2.7              5.1                  1.9          virginica
...    

 

split()의 실행 결과가 리스트므로, split() 후 lapply()를 적용하면 iris의 종별 Sepal.Length의 평균을 구할 수 있다. 다음 코드를 앞서 설명한 tapply()의 경우와 비교해보기 바란다.

>lapply(split(iris$Sepal.Length, iris$Species), mean)
$setosa
[1] 5.006

$versicolor
[1]5.936

$virginica
[1]6.588

 

subset()

subset()은 split()과 유사하지만 전체를 부분으로 구분하는 대신 조건을 만족하는 특정 부분만 취하는 용도로 사용한다.

 

-subset : 조건을 만족하는 벡터, 행렬, 데이터 프레임의 일부를 반환한다.

subset(

   x,           #일부를 취할 객체

   subset     #데이터를 취할 것인지 여부

)

 

subset(

   x,

   subset,

   select          #데이터 프레임의 경우 선택하고자 하는 컬럼

)

 

다음은 iris에서 setosa 종만 뽑아내는 예다.

>subset(iris, Species=="setosa")
     Sepal.Length   Sepal.Width   Petal.Length   Petal.Width    Species
1           5.1               3.5            1.4               0.2          setosa
2           4.9               3.0            1.4               0.2          setosa
...

 

"벡터 연산"에서 살펴봤듯이 벡터 간 연산에서의 AND, OR는 &&, ||가 아니라 &,|를 사용해야 한다. 따라서 subset()에서 2개 이상의 조건을 조합할 때는 &나 |를 사용한다. 다음은 setosa종에서 Sepal.Length가 5.0 이상인 행을 추출하는 예다.

>subset(iris, Species=="setosa"&Sepal.Length > 5.0)
     Sepal.Length   Sepal.Width   Petal.Length   Petal.Width    Species
1          5.1               3.5              1.4                0.2         setosa
6          5.4               3.9              1.7                0.4         setosa
...

 

subset에 select 인자를 지정하면 특정 컬럼을 선택하거나 제외할 수 있다. 다음은 Sepal.Length와 Species 컬럼을 iris에서 선택하여 출력한 예다.

>subset(iris, select=c(Sepal.Length, Species))
      Sepal.Length   Species
1            5.1        setosa
2            4.9        setosa
3            4.7        setosa
...

 

반대로 특정 컬럼을 제외하고자 한다면 -를 컬럼 이름 앞에 붙인다.

>subset(iris, select=-c(Sepal.Length, Species))
        Sepal.Width   Petal.Length   Petal.Width
1           3.5             1.4                  0.2
2           3.0             1.4                  0.2
...

 

select에서 컬럼을 제외하는 방법을 names()와 %in%을 사용하여 제외하는 방법과 비교해서 알아두기 바란다.

>iris(,!names(iris) %in% c("Sepal.Length","Species"))
      Sepal.Width Petal.Length Petal.Width
1         3.5            1.4             0.2
2         3.0            1.4             0.2
...

 

데이터 병합

merge()는 두 데이터 프레임을 공통된 값을 기준으로 묶는 함수다. merge()는 데이터베이스에서 join과 같은 역할을 한다.

-merge: 공통된 컬럼명 또는 행 이름에 따라 데이터 프레임을 병합한다.

merge(

   x,           #병합할 데이터 프레임

   y           #병합할 데이터 프레임

)

 

merge(

   x,

   y,

   by,         #병합 기준으로 사용할 컬럼

   #데이터프레임 x, y에서 병합에 사용할 컬럼이 각각 다르다면 by.x, by.y에 이를 지정

   by.x=by,

   by.y=by,

   #all은 공통된 값이 x,y 중 한쪽에 없을 때의 처리를 뜻한다. 기본값은 FALSE로 x,y 모두에

   #공통된 데이터가 있을때만 해당 행이 병합 결과에 포함된다. all=TRUE면

   #x,y 중 어느 한쪽에 공통된 값을 가지는 행이 없을 때 해당 쪽을 NA로 채워 병합하여

   #결과적으로 x,y의 전체 행이 결과에 포함된다.

   all=FALSE,

   #all.x, all.y를 통해 x,y 중 특정 쪽에 공통된 값이 없더라도 항상 결과에 포함되게 할 수 있다.

   all.x,

   all.y

)

 

다음은 이름(name)컬럼을 기준으로 수학 점수가 저장된 데이터 프레임과 영어 점수가 저장된 데이터 프레임을 병합한 예다. x와 y에 name값이 서로 다른 순서로 저장되어 있으나 공통된 name값을 기준으로 점수가 잘 병합된 것을 볼 수있다.

>x<-data.frame(name=c("a","b","c"), math=c(1,2,3))
>y<-data.frame(name=c("c","b","a"), english=c=4,5,6))
    name   math   english
1   a          1         6
2   b          2         5
3   c          3         4

 

merge()는 cbind()와는 다르다. 앞의 코드는 두 개의 데이터 프레임을 합칠 떄 공통되는 컬럼인 name을 기준으로 데이터를 합치지만 cbind()는 다음에 보인 것처럼 단순히 컬럼을 합칠 뿐이다.

>x<-data.frame(name=c("a","b","c"), math=c(1,2,3))
>y<-data.frame(name=c("c","b","a"), english=c=4,5,6))
>cbind(x,y
    name     math    name     english
1    a           1         c           4
2    b           2        b           5
3    c           3         a          6

 

merge() 수행 시 공통된 값이 한쪽에만 있는 경우에는 반대편 데이터가 비게 되고 이 경우 해당 행은 병합 결과에서 빠진다. 그러나 이 경우에도 데이터가 비어 이쓴 쪽의 값을 NA로 채우면서 전체 데이터를 모두 병합하고 싶다면 all 인자에 TRUE를 지정한다.

 

다음에 all=FALSE(기본값)인 경우와 all=TRUE인 경우의 비교를 보였다. all=FALSE인 경우 공통된 name이 양측에 포함된 "a","b"만 결과에 나타나며, all=True인 경우 공통된 값이 없는 쪽에 NA가 채워지면서 x,y의 전체 행이 결과에 포함된다.

>x<-data.frame(name=c("a","b","c"),
+                   math=c(1,2,3))
>x<-data.frame(name=c("a","b","c"),
+                   english=c(4,5,6))
>merge(x,y)
     name   math   english
1      a        1         4
2      b        2         5
>merge(x,y,all=TRUE)
     name   math   english
1     a         1          4
2     b         2          5
3     c         3         NA
4     d         NA        6

 

R을 이용한 데이터 처리&분석 실무 中

반응형

'R > R을 이용한 데이터 처리&분석 실무' 카테고리의 다른 글

데이터 구조의 변형과 요약  (0) 2020.02.03
데이터 정렬  (0) 2020.02.03
apply 계열 함수 - 2  (0) 2020.02.02
apply 계열 함수 - 1  (0) 2020.02.01
데이터 프레임의 행과 컬럼 합치기  (0) 2020.01.31