지난번 포스팅에서는 PostgreSQL, Greenplum database에서 SQL, MADlib 을 사용하여 연수형 데이터의 집계/ 요약통계량(aggregation/ summary statistics)을 구하는 방법(https://rfriend.tistory.com/580)을 소개하였습니다.

이번 포스팅에서는 PostgreSQL, Greenplum DB에서 SQL, Apache MADlib 을 사용하여 여러개의 연속형 변수들 간의 상관관계를 구하는 방법을 소개하겠습니다.

(1) SQL 로 두개 연속형 변수간 상관계수 구하기
(2) SQL 로 다수의 연속형 변수간 상관계수 행렬(Correlation Matrix) 구하기
(3) MADlib으로 다수의 연속형 변수간 상관계수 행렬 구하기
(4) MADlib으로 다수의 연속형 변수간 그룹별로 상관계수 행렬(Correlation Matrix by Group) 구하기



예제로 사용하도록 연속형 데이터 4개 칼럼과 범주형 데이터 1개를 가지고 iris 샘플 데이터를 테이블로 만들어보겠습니다.



-- Iris data table
DROP TABLE IF EXISTS iris;
CREATE TABLE iris (id INT, sepal_length FLOAT, sepal_width FLOAT,
                    petal_length FLOAT, petal_width FLOAT,
                   class_name TEXT);
INSERT INTO iris VALUES
(1,5.1,3.5,1.4,0.2,'Iris-setosa'),
(2,4.9,3.0,1.4,0.2,'Iris-setosa'),
(3,4.7,3.2,1.3,0.2,'Iris-setosa'),
(4,4.6,3.1,1.5,0.2,'Iris-setosa'),
(5,5.0,3.6,1.4,0.2,'Iris-setosa'),
(6,5.4,3.9,1.7,0.4,'Iris-setosa'),
(7,4.6,3.4,1.4,0.3,'Iris-setosa'),
(8,5.0,3.4,1.5,0.2,'Iris-setosa'),
(9,4.4,2.9,1.4,0.2,'Iris-setosa'),
(10,4.9,3.1,1.5,0.1,'Iris-setosa'),
(11,7.0,3.2,4.7,1.4,'Iris-versicolor'),
(12,6.4,3.2,4.5,1.5,'Iris-versicolor'),
(13,6.9,3.1,4.9,1.5,'Iris-versicolor'),
(14,5.5,2.3,4.0,1.3,'Iris-versicolor'),
(15,6.5,2.8,4.6,1.5,'Iris-versicolor'),
(16,5.7,2.8,4.5,1.3,'Iris-versicolor'),
(17,6.3,3.3,4.7,1.6,'Iris-versicolor'),
(18,4.9,2.4,3.3,1.0,'Iris-versicolor'),
(19,6.6,2.9,4.6,1.3,'Iris-versicolor'),
(20,5.2,2.7,3.9,1.4,'Iris-versicolor'),
(21,6.3,3.3,6.0,2.5,'Iris-virginica'),
(22,5.8,2.7,5.1,1.9,'Iris-virginica'),
(23,7.1,3.0,5.9,2.1,'Iris-virginica'),
(24,6.3,2.9,5.6,1.8,'Iris-virginica'),
(25,6.5,3.0,5.8,2.2,'Iris-virginica'),
(26,7.6,3.0,6.6,2.1,'Iris-virginica'),
(27,4.9,2.5,4.5,1.7,'Iris-virginica'),
(28,7.3,2.9,6.3,1.8,'Iris-virginica'),
(29,6.7,2.5,5.8,1.8,'Iris-virginica'),
(30,7.2,3.6,6.1,2.5,'Iris-virginica');



SELECT * FROM iris ORDER BY id LIMIT 5;






  (1) SQL 로 두개 연속형 변수간 상관계수 구하기


공분산(Covariance)은 두 변량이 각각의 평균으로부터 변화하는 방향 및 양에 대한 기대값입니다. PostgreSQL, Greenplum DB에서 모집단의 공분산(Population Covariance)는 COVAR_POP(Y, X) 함수를 사용하며, 샘플 공분산(Sample Covariance)은 COVAR_SAMP(Y, X) 함수를 사용합니다.

(* 공분산, 상관계수 참고: https://rfriend.tistory.com/126)


피어슨 상관계수(Pearson's Correlation Coefficient)는 공분산을 표준편차로 나누어서 표준화해준 값으로서, -1~1 사이의 값을 가집니다. 1에 가까울수록 두 변수간에 양의 선형관계가 있고, -1에 가까울수록 음의 선형관계가 있으며, 0이면 선형관계가 없다고 해석합니다. PostgreSQL, Greenplum DB에서는 CORR(Y, X) 함수를 사용합니다.



----- b/w Y and X
-- Population Covariance using SQL: covar_pop(Y, X)
SELECT COVAR_POP(sepal_length, sepal_width) FROM iris;


-- Sample Covariance using SQL: covar_samp(Y, X)
SELECT COVAR_SAMP(sepal_width, sepal_length) FROM iris;


-- Pearson's Correlation Coefficients using SQL: corr(Y, X)
SELECT CORR(sepal_width, sepal_length) FROM iris;





  (2) SQL 로 다수의 연속형 변수간 상관계수 행렬(Correlation Matrix) 구하기


먼저, 이해를 돕기 위해서 2단계로 나누어서 과정을 설명하자면요, 긴 형태(long format)로 두 연속형 변수 간의 상관계수를 구해보겠습니다. (두번째 단계에서 Pivoting 하는데 사용하는, sub query 의 내용임)


------ Correlation Coefficients among multiple variables
-- Correlation Matrix

-- (a) Calculating pairwise correlation using corr(Y, X) function

SELECT
    1 AS column_position
    , 'sepal_length' AS row
    , 'sepal_width' AS col
    , CORR(sepal_length, sepal_width) AS corr_coef
FROM iris
UNION
SELECT

    1 AS column_position
    , 'sepal_length' AS row
    , 'petal_length' AS col
    , CORR(sepal_length, petal_length) AS corr_coef
FROM iris
UNION
SELECT

    1 AS column_position
    , 'sepal_length' AS row
    , 'petal_width' AS col
    , CORR(sepal_length, petal_width) AS corr_coef
FROM iris
UNION
SELECT

    2 AS column_position
    , 'sepal_width' AS row
    , 'petal_length' AS col
    , CORR(sepal_width, petal_length) AS corr_coef
FROM iris
UNION
SELECT

    2 AS column_position
    , 'sepal_width' AS row
    , 'petal_width' AS col
    , CORR(sepal_width, petal_width) AS corr_coef
FROM iris
UNION
SELECT

    3 AS column_position
    , 'petal_length' AS row
    , 'petal_width' AS col
    , CORR(petal_length, petal_width) AS corr_coef
FROM iris;




위의 SQL query를 sub query 로 넣고, manual 하게 테이블을 Pivot 하여 우리가 원하는 상관계수 행렬 (correlation matrix)를 만들어보겠습니다. 대각행렬에서 우상단에만 상관계수를 나타내고 좌하단에는 0으로 채워넣기를 하였습니다.



-- (b) Pivoting the table to get a correlation matrix

SELECT
    column_position
    , row
    , SUM(CASE WHEN col='sepal_length' THEN corr_coef ELSE 0 END) AS sepal_length
    , SUM(CASE WHEN col='sepal_width' THEN corr_coef ELSE 0 END) AS sepal_width
    , SUM(CASE WHEN col='petal_length' THEN corr_coef ELSE 0 END) AS petal_length
    , SUM(CASE WHEN col='petal_width' THEN corr_coef ELSE 0 END) AS petal_width
FROM (
    SELECT
        1 AS column_position
        , 'sepal_length' AS row
        , 'sepal_width' AS col
        , CORR(sepal_length, sepal_width) AS corr_coef
    FROM iris
    UNION
    SELECT

        1 AS column_position
        , 'sepal_length' AS row
        , 'petal_length' AS col
        , CORR(sepal_length, petal_length) AS corr_coef
    FROM iris
    UNION
    SELECT

        1 AS column_position
        , 'sepal_length' AS row
        , 'petal_width' AS col
        , CORR(sepal_length, petal_width) AS corr_coef
    FROM iris
    UNION
    SELECT

        2 AS column_position
        , 'sepal_width' AS row
        , 'petal_length' AS col
        , CORR(sepal_width, petal_length) AS corr_coef
    FROM iris
    UNION
    SELECT

        2 AS column_position
        , 'sepal_width' AS row
        , 'petal_width' AS col
        , CORR(sepal_width, petal_width) AS corr_coef
    FROM iris
    UNION
    SELECT
        3 AS column_position
        , 'petal_length' AS row
        , 'petal_width' AS col
        , CORR(petal_length, petal_width) AS corr_coef
    FROM iris
) a
GROUP BY column_position, row
ORDER BY column_position;




원하는 상관계수행렬을 구하기는 했는데요, SQL query가 엄청 길어지고 또 복잡해졌습니다. 분석의 대상이 되는 연속형 데이터 칼럼 수가 늘어날수록 query가 더 길어지고 복잡해지는 구조여서 더 좋은 방법이 없을까 고민하게 됩니다. 짜잔~! 이럴때 PostgreSQL, Greenplum DB에서 쉽고 편하고 또 빠르게 분석하는데 쓸 수 있는 SQL 기반의 오픈소스 분석툴인 Apache MADlib이 있습니다!




  (3) MADlib으로 다수의 연속형 변수간 상관계수 행렬 구하기


위의 (2)번에서 pure SQL로 했던 상관계수 행렬 구하기를 Apache MADlib의 madlib.correlation() 함수를 사용하면 아래처럼 단 3줄이면 끝납니다! 비교할 수 없을 정도로 SQL query가 간소해졌습니다!



----- Correlation Matrix using MADlib
DROP TABLE IF EXISTS iris_corr_output, iris_corr_output_summary;
SELECT madlib.correlation( 'iris',             -- source table
                           'iris_corr_output',       -- output table
                           'sepal_length, sepal_width, petal_length, petal_width' -- target columns
                         );


/*                         
SELECT madlib.correlation( 'iris',        -- source table
                           'iris_corr_output',  -- output table
                           '*'                     -- for all columns
                         );                        
*/
                       


SELECT * FROM iris_corr_output ORDER BY column_position;






  (4) MADlib으로 다수의 연속형 변수간 그룹별로 상관계수 행렬구하기

       (Correlation Matrix by Group using Apache MADlib)


PostgreSQL, Greenplum DB에서 Apache MADlib을 사용했을 때 코드가 간소해지는점 말고 또 좋은 점 중의 하나는 그룹별 연산을 하기에도 굉장히 편리하다는 점입니다.


아래 예제는 class_name ('iris-setosa', 'iris-versicolor', 'iris-virginica') 의 그룹별로 상관계수 행렬을 구하기(correlation matrix by groups using MADlib) 입니다. 위의 (3)번 예제어서 'grouping column' 위치에 "class_name" 칼럼 이름만 추가하면 끝입니다. MADlib이 이처럼 "simple & powerful" 합니다. (만약 (2)번 방법으로 SQL로 일일이 group by 넣어서 query 짠다고 상상을 해보면 끔찍하지 않나요? ^^;)



-- Correlation Matrix by Groups using MADlib
DROP TABLE IF EXISTS iris_corr_grp_output, iris_corr_grp_output_summary;
SELECT madlib.correlation( 'iris'             -- source table
                           , 'iris_corr_grp_output' -- output table
                           , '*' -- target columns
                           , False -- verbose
                           , 'class_name' -- grouping column
                         );
                         


SELECT * FROM iris_corr_grp_output ORDER BY class_name, column_position;




[Reference]
* PostgreSQL 9.4: https://www.postgresql.org/docs/9.4/functions-aggregate.html
* Apache MADlib: https://madlib.apache.org/docs/v1.0/group__grp__correlation.html

이번 포스팅이 많은 도움이 되었기를 바랍니다 .
행복한 데이터 과학자 되세요!  :-)




728x90
반응형
Posted by Rfriend
,

다변량 통계분석의 경우 두 변수 간의 상관관계에 아주 많이 의존합니다.  따라서 상관관계 두 연속형 변수 (continuous variable)의 상관관계를 분석하는 것이 매우 중요한데요, 상관관계 분석 기법으로는

 

통계량 분석

 

  (1) 공분산 (covariance)

  (2) 상관계수 (correlation coefficient)

 

 

그래프 분석 

 

  (1) 산점도 (scatter plot)

  (2) 산점도 행렬(scatter matrix plot)

  (3) 상관계수행렬(correlation coefficient plot)

 

등이 있습니다. 

 

그래프는 오른쪽 메뉴의 'R 그래프/시각화'에서 ggplot 을 이용해서 그래프 작성하는 방법을 이미 소개하였으므로, 이번 포스팅에서는 통계량 분석에 대해서만 알아보도록 하겠습니다.

 

 

R 분석 예제 데이터는 MASS 패키지 내 Cars93 데이터프레임의 고속도로연비(MPG.highway)와 무게(Weight) 연속형 변수를 사용하겠습니다.

 

> library(MASS)
> str(Cars93)
'data.frame':	93 obs. of  27 variables:
 $ Manufacturer      : Factor w/ 32 levels "Acura","Audi",..: 1 1 2 2 3 4 4 4 4 5 ...
 $ Model             : Factor w/ 93 levels "100","190E","240",..: 49 56 9 1 6 24 54 74 73 35 ...
 $ Type              : Factor w/ 6 levels "Compact","Large",..: 4 3 1 3 3 3 2 2 3 2 ...
 $ Min.Price         : num  12.9 29.2 25.9 30.8 23.7 14.2 19.9 22.6 26.3 33 ...
 $ Price             : num  15.9 33.9 29.1 37.7 30 15.7 20.8 23.7 26.3 34.7 ...
 $ Max.Price         : num  18.8 38.7 32.3 44.6 36.2 17.3 21.7 24.9 26.3 36.3 ...
 $ MPG.city          : int  25 18 20 19 22 22 19 16 19 16 ...
 $ MPG.highway       : int  31 25 26 26 30 31 28 25 27 25 ...
 $ AirBags           : Factor w/ 3 levels "Driver & Passenger",..: 3 1 2 1 2 2 2 2 2 2 ...
 $ DriveTrain        : Factor w/ 3 levels "4WD","Front",..: 2 2 2 2 3 2 2 3 2 2 ...
 $ Cylinders         : Factor w/ 6 levels "3","4","5","6",..: 2 4 4 4 2 2 4 4 4 5 ...
 $ EngineSize        : num  1.8 3.2 2.8 2.8 3.5 2.2 3.8 5.7 3.8 4.9 ...
 $ Horsepower        : int  140 200 172 172 208 110 170 180 170 200 ...
 $ RPM               : int  6300 5500 5500 5500 5700 5200 4800 4000 4800 4100 ...
 $ Rev.per.mile      : int  2890 2335 2280 2535 2545 2565 1570 1320 1690 1510 ...
 $ Man.trans.avail   : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 1 1 1 1 1 ...
 $ Fuel.tank.capacity: num  13.2 18 16.9 21.1 21.1 16.4 18 23 18.8 18 ...
 $ Passengers        : int  5 5 5 6 4 6 6 6 5 6 ...
 $ Length            : int  177 195 180 193 186 189 200 216 198 206 ...
 $ Wheelbase         : int  102 115 102 106 109 105 111 116 108 114 ...
 $ Width             : int  68 71 67 70 69 69 74 78 73 73 ...
 $ Turn.circle       : int  37 38 37 37 39 41 42 45 41 43 ...
 $ Rear.seat.room    : num  26.5 30 28 31 27 28 30.5 30.5 26.5 35 ...
 $ Luggage.room      : int  11 15 14 17 13 16 17 21 14 18 ...
 $ Weight            : int  2705 3560 3375 3405 3640 2880 3470 4105 3495 3620 ...
 $ Origin            : Factor w/ 2 levels "USA","non-USA": 2 2 2 2 2 1 1 1 1 1 ...
 $ Make              : Factor w/ 93 levels "Acura Integra",..: 1 2 4 3 5 6 7 9 8 10 ...

 

 

 

 

상식적으로 생각해보면 차 무게가 많이 나갈수록 고속도로연비가 안좋게 나올텐데요, 아래의 산점도를 보면 역(-)의 상관관계가 있음을 알 수 있습니다.

 

> # Scatter Plot of MPG.highway ~ Weight with linear regression line 
> plot(MPG.highway ~ Weight, data = Cars93, 
+      main = "Scatter Plot of MPG.highway ~ Weight", 
+      xlab = "Weight", ylab = "MPG.highway")
> abline(lm(MPG.highway ~ Weight, data = Cars93), col = "blue", lty = 2)
 

 

 

 

 

 

그럼, 먼저 공분산(covariance)을 알아보고, 그 다음으로 상관계수(correlation coefficient)를 알아보겠습니다.

 

 

(1) 공분산 (covariance) : cov()

 

 

공분산의 이해를 돕기 위해 x가 증가할 때 y도 역시 증가하는 경우를 가정해보면서 설명을 해보겠습니다.

 

- μ(x) 보다 큰 x값에 대응하는 y값도 또한 μ(y)보다 크므로 (X-μ(x)(Y-μ(y))는 양수가 됩니다.(+*+=+)

- μ(x) 보다 작은 x값에 대응하는 y값도 또한 μ(y)보다 작으므로 (X-μ(x)(Y-μ(y))는 양수가 됩니다.(-*-=+)

 

 

반대로, x가 증가할 때 y는 감소하는 경우를 가정해봅시다. 이 경우에는,

 

- μ(x) 보다 큰 x값에 대응하는 y값은 μ(y)보다 작으므로 (X-μ(x)(Y-μ(y))는 음수가 됩니다.(+*-=-)

- μ(x) 보다 작은 x값에 대응하는 y값은 μ(y)보다 크므로 (X-μ(x)(Y-μ(y))는 음수가 됩니다.(-*+=-)

 

즉, 공분산(covriance) 값이 '+'이면 x와 y 두 변수는 같은 방향으로 움직이며 (x가 증가하면 y도 증가, x가 감소하면 y도 감소), 공분산이 '-'이면 x와 y 두 변수는 서로 다른 방향으로 움직인다는 것을 알 수 있습니다.

 

 

R의 cov() 함수를 사용해서 고속도로연비(MPG.highway)와 무게(Weight)와의 공분산을 2가지 방법을 사용해서 구해보겠습니다.

 

 

> ##-- covariance 
> # way 1. cov(x, y)
> with(Cars93, cov(x=MPG.highway, 
+                  y=Weight, 
+                  use="complete.obs", 
+                  method=c("pearson")))
[1] -2549.655
> # way 2. cov(x, y=NULL)
> x <- Cars93[c("MPG.highway", "Weight")]
> with(Cars93, cov(x, 
+                  y=NULL, 
+                  use="complete.obs", 
+                  method=c("pearson")))
            MPG.highway     Weight
MPG.highway     28.4273  -2549.655
Weight       -2549.6546 347977.893

 

 

way 1. cov(x, y)를 사용(x, y는 벡터)하든지,  way 2. cov(x, y=NULL)을 사용(x는 데이터프레임)하든지 결과는 pearson covariance 가 -2549.6546 으로 음의 상관관계를 가지는 것으로 나왔습니다.

 

그런데 단위가 -2549.6546 이면 어느정도로 음의 상관관계라고 하는 것인지 감이 안잡힙니다. 이때 공분산을 표준화한 상관계수를 사용하면 두 변수간의 상관관계의 정도를 가늠할 수 있게 됩니다.

 

 

 

(2) 상관계수 (pearson correlation coefficient) : cor() 

 

 

두 변수간의 관련성을 나타내는 측도서 상관계수는 다음의 특징을 가집니다.

 

  1) 표준화변수들의 공분산은 상관계수가 된다.

  2) 상관계수는 -1 ≤ ρ ≤ 1 의 범위의 값을 가진다.

  3) 상관계수 ρ가 +1에 가까울수록 강한 양의 선형관계를 가지며,

      -1에 가까울수록 강한 음의 선형관계를 가진다.

  4) 상관계수 ρ = 0 이면 두 변수간의 선형관계는 없으며,

      0에 가까울수록 선형관계가 약해진다.

      (단, 비선형 관계를 가질 수는 있음. 그래프 분석 병행 필요)

  5) 위치 변환이나 척도 변환 후에도 상관계수는 변함이 없다. 

 

 

R의 cor() 함수를 사용해서 고속도로연비(MPG.highway)와 무게(Weight)의 pearson 상관계수(pearson correlation coefficient)를 구해보면 다음과 같습니다.

 

 

> ##-- correlation coefficient
> # way 1. cor(x, y)
> with(Cars93, cor(x=MPG.highway, 
+                  y=Weight, 
+                  use="complete.obs", 
+                  method=c("pearson")))
[1] -0.8106581
> 
> 
> x <- Cars93[c("MPG.highway", "Weight")]
> cor(x, 
+     y=NULL, 
+     use="complete.obs", 
+     method=c("pearson"))
            MPG.highway     Weight
MPG.highway   1.0000000 -0.8106581
Weight       -0.8106581  1.0000000
> 
> 
> # options
> # use = c("everythig", "all.obs", "complete.obs", "na.or.complete", pairwise.complete.obs")
> # method = c("pearson", "kendall", "spearman")
 

 

고속도로연비(MPG.highway)와 무게(Weight)의 pearson 상관계수는 -0.8106581 으로서 매우 강한 음의 상관관계를 가지는 것으로 나왔습니다.

 

 

cov()와 cor() 함수에 공통으로 use와 method option이 사용되었는데요, 이에 대해 추가 설명을 하겠습니다.

 

 구분

option 

내용 

 use =

(결측값

처리)

"everything" (default)

 결측값이 있을 경우 NA로 계산 결과 제시

 "all.obs"

 결측값이 있을 경우 오류 발생

 ("Error in cor(x = a, y = b, use = "all.obs", method = c("pearson")) : cov/cor에 결측치들이 있습니다

" error message)

 "complete.obs"

 결측값이 있는 case는 모두 제거된 상태에서 상관계수 계산

 "pairwise.complete.obs"

 상관계수가 계산되는 변수들만을 대상으로 결측값이 있는

 case 제거한  상관계수 계산

 method =

(상관계수
통계량)

 "pearson" (default)

 Pearson correlation coefficient 지정,

 가장 일반적으로 사용

 "kendall"

 Kendall의 순위상관계수 혹은 Kendall의 τ (tau) 지정,

 비모수 상관계수 계산 (정규성 불충족 시)

 "spearman"

 Spearman의 순위상관계수 혹은 Spearman이 ρ(rho) 지정,

 비모수 상관계수 계산 (정규성 불충족 시)

* kendall τ , Spearman ρ 수식은 생략함

 

 

 

아래에는 결측값(NA, missing value)이 포함되어 있을 경우 공분산이나 상관계수 계산 시에 결측값을 처리하는 옵션인 'use' 의 세부 옵션별("everything", "all.obs", "complete.obs", "pairwise.complete.obs")로 어떻게 다른지를 간단한 예제를 들어보았습니다.

 

a 벡터의 5번째 원소에 NA가 들어있고, c 벡터의 1번째 원소에 NA가 들어있는 예제입니다.  use 옵션을 좀더 명확히 이해하는데 도움이 되기를 바랍니다.

 

 - use = "everything" : NA가 포함되어 있으므로 결과는 "NA"

 - use = "all.obs" : NA가 포함되어 있으므로 다음과 같은 error message => "cov/cor에 결측치들이 있습니다"

 - use = "complete.obs" : a, b, c 벡터에서 한개라도 NA가 있으면 그 순번째의 a, b, c 벡터의 원소(만약 데이터 프레임이라면 해당 row 전체, 즉 해당 observation case의 모든 변수)는 통째로 삭제하라는 뜻이므로 a, b, c 벡터 모두의 1번째와 5번째 원소 삭제한 후에 상관계수 계산

 - use = "pairwise.compelte.obs" : a와 b의 짝 (pairwise b/w a and b)에서는 5번째 원소 삭제, a와 c 의 짝(pairwise b/w a and d)에서는 1번째와 5번째 원소 삭제, b와 c의 짝(pairwise b/w b and c)에서는 1번째 원소 삭제한 후에 상관계수 계산

 

> ##------------
> ## cov(), cor()
> ## use : an optional character string giving a method for computing covariances 
> ##       in the presence of missing values
> ##------------
> 
> # dataset for correlation analysis with NAs
> a <- c(10, 9, 8, 6, NA)
> b <- c(9, 6, 4, 3, 2)
> c <- c(NA, 13, 18, 20, 25)
> 
> x <- data.frame(a, b, c)
> 
> 
> ##------------
> # use = "everything"  
> #  ; (default setting) NAs will propagate conceptually, 
> #    i.e., a resulting value will be NA whenever one of its contributing observations is NA
> cor(x, 
+     y = NULL, 
+     use = "everything", 
+     method = c("pearson"))
   a  b  c
a  1 NA NA
b NA  1 NA
c NA NA  1
> 
> 
> ##------------
> # use = "all.obs" 
> # ; the presence of missing observations will produce an error
> cor(x, 
+     y = NULL, 
+     use = "all.obs", 
+     method = c("pearson"))
Error in cor(x, y = NULL, use = "all.obs", method = c("pearson")) : 
  cov/cor에 결측치들이 있습니다
> 
> 
> ##------------
> # use = "complete.obs" 
> #  ; missing values are handled by casewise deletion 
> #    (and if there are no complete cases, that gives an error)
> cor(x, 
+     y = NULL, 
+     use = "complete.obs", 
+     method = c("pearson"))
           a          b          c
a  1.0000000  0.9285714 -0.9078413
b  0.9285714  1.0000000 -0.9986254
c -0.9078413 -0.9986254  1.0000000
> 
> 
> # double check
> a <- c(10, 9, 8, 6, NA)
> b <- c(9, 6, 4, 3, 2)
> c <- c(NA, 13, 18, 20, 25)
> 
>   # use = "complete.obs" : delete 1st and 5th elements of a, b, c vectors
> a_complete.obs <- c(9, 8, 6)
> b_complete.obs <- c(6, 4, 3)
> c_complete.obs <- c(13, 18, 20)
> x_complete.obs <- data.frame(a_complete.obs, b_complete.obs, c_complete.obs)
> 
> cor(x_complete.obs, 
+     y = NULL, 
+     use = "all.obs", # because it is calculated after deleting 1st and 5th elements
+     method = c("pearson"))
               a_complete.obs b_complete.obs c_complete.obs
a_complete.obs      1.0000000      0.9285714     -0.9078413
b_complete.obs      0.9285714      1.0000000     -0.9986254
c_complete.obs     -0.9078413     -0.9986254      1.0000000
> 
> 
> ##------------
> # use = "pairwise.complete.obs" 
> #  ; the correlation or covariance between each pair of 
> #    variables is computed using all complete pairs of observations on those variables
> #    only works with the "pearson" method
> cor(x, 
+     y = NULL, 
+     use = "pairwise.complete.obs", 
+     method = c("pearson"))
           a          b          c
a  1.0000000  0.9221389 -0.9078413
b  0.9221389  1.0000000 -0.9824719
c -0.9078413 -0.9824719  1.0000000
> 
> # double check 
> a <- c(10, 9, 8, 6, NA)
> b <- c(9, 6, 4, 3, 2)
> c <- c(NA, 13, 18, 20, 25)
>   
>   # use = "pairwise.complete.obs" : delete 5th element of a and b pair vectors
> a_ab_pairwise.complete.obs <- c(10, 9, 8, 6)
> b_ab_pairwise.complete.obs <- c(9, 6, 4, 3)
> 
> cor(x = a_ab_pairwise.complete.obs, 
+     y = b_ab_pairwise.complete.obs, 
+     use = "all.obs", # because it is calculated after deleting 5th element
+     method = c("pearson"))
[1] 0.9221389
> 
>   # use = "pairwise.complete.obs" : delete 1st and 5th elements of a and c pair vectors
> a_ac_pairwise.complete.obs <- c(9, 8, 6)
> c_ac_pairwise.complete.obs <- c(13, 18, 20)
> 
> cor(x = a_ac_pairwise.complete.obs, 
+     y = c_ac_pairwise.complete.obs, 
+     use = "all.obs", 
+     method = c("pearson"))
[1] -0.9078413
> 
>   # use = "pairwise.complete.obs" : delete 1st element of b and c pair vectors
> b_bc_pairwise.complete.obs <- c(6, 4, 3, 2)
> c_bc_pairwise.complete.obs <- c(13, 18, 20, 25)
> 
> cor(x = b_bc_pairwise.complete.obs, 
+     y = c_bc_pairwise.complete.obs, 
+     use = "all.obs", 
+     method = c("pearson"))
[1] -0.9824719

 

 



(3) 여러개의 숫자형 변수 간 상관계수 결과를 세로로 긴 형태(Long Format)로 저장하기


여러개의 숫자형 변수로 이루어진 데이터 프레임에서 숫자형 변수의 짝(pairs) 별로 상관계수를 구해서 세로로 길쭉한 형태(long format)으로 결과를 저장하고 싶다면 아래의 for loop 문을 사용한 예제를 참고하세요. 


표준정규분포로 부터 10개 칼럼, 5개 관측치의 난수를 생성하여 예제 숫자형 데이터 프레임을 만들었습니다.


for loop 순환문으로 칼럼 갯수만큼 i, j 를 돌리면 두개의 변수 쌍(pairs)이 두 번씩 출현할텐데요, 두 변수의 순서가 바뀌어도 상관계수 값은 동일하므로 두 변수 쌍은 한번만 계산하도록 for loop 문을 작성했습니다. 그리고 자기 자신과의 상관계수는 항상 '1'이므로 제외하도록 했습니다.  



# generate 50 random numbers from standard normal distribution X~N(0, 1)

set.seed(1004)

x <- rnorm(50, mean=0, sd=1)

df <- data.frame(matrix(x, nrow=5, ncol=10, byrow=TRUE))

df

# X1         X2         X3          X4          X5         X6        X7        X8         X9        X10

# 1 -0.6078408  0.7676292 -0.1642718 -0.02877676  0.01355787 -0.7157169 -1.477976 0.8280146 -0.8951765  1.8841561

# 2 -1.8952567  1.1259354  0.1494180 -0.21511242  2.63756778 -0.2678609  1.123417 0.4842308  0.6318069 -0.8180967

# 3 -0.7470136 -0.5132835  0.8709808  0.83062565 -1.03451768 -1.6140827  2.169269 0.6719930  0.4054343 -0.8316793

# 4  0.9159031  0.3905532 -0.6347263 -1.00658131  0.35622463  0.1083284 -1.712486 0.6846194 -0.6083049 -0.6192043

# 5 -0.7671233  0.3633518 -0.7325597  1.23058116  0.09165232  1.5699387  1.309473 0.9069780 -1.3729150 -0.1163513



# pearson's correlation coefficients in a long format

cor_long <- data.frame() # blank dataframe to save the corr results later

col_nm <- colnames(df)

n <- 1


for (i in 1:(ncol(df)-1)){

  for (j in (i+1):ncol(df)) {

    cor_long[n, 1] <- col_nm[i]

    cor_long[n, 2] <- col_nm[j]

    cor_long[n, 3] <- cor(df[,i], df[,j])

    n <- n+1

  }

}


# rename column names

colnames(cor_long) <- c("col_1", "col_2", "corr_coef")


cor_long

# col_1 col_2    corr_coef

# 1     X1    X2 -0.332162830

# 2     X1    X3 -0.448170165

# 3     X1    X4 -0.438930937

# 4     X1    X5 -0.497470094

# 5     X1    X6  0.100596534

# 6     X1    X7 -0.643972517

# 7     X1    X8  0.346978141

# 8     X1    X9 -0.465219120

# 9     X1   X10  0.051698753

# 10    X2    X3 -0.440364182

# 11    X2    X4 -0.454194089

# 12    X2    X5  0.847973001

# 13    X2    X6  0.342903949

# 14    X2    X7 -0.413224712

# 15    X2    X8 -0.235257160

# 16    X2    X9 -0.064519846

# 17    X2   X10  0.314659871

# 18    X3    X4  0.224054384

# 19    X3    X5 -0.167990551

# 20    X3    X6 -0.865225316

# 21    X3    X7  0.560975754

# 22    X3    X8 -0.500395969

# 23    X3    X9  0.805120716

# 24    X3   X10 -0.244220838

# 25    X4    X5 -0.419495665

# 26    X4    X6  0.170965784

# 27    X4    X7  0.755460153

# 28    X4    X8  0.482063832

# 29    X4    X9 -0.181887756

# 30    X4   X10 -0.001894032

# 31    X5    X6  0.239111079

# 32    X5    X7 -0.039280725

# 33    X5    X8 -0.632907538

# 34    X5    X9  0.356088708

# 35    X5   X10 -0.209073460

# 36    X6    X7 -0.074444629

# 37    X6    X8  0.457440745

# 38    X6    X9 -0.681812940

# 39    X6   X10 -0.023974644

# 40    X7    X8 -0.189050606

# 41    X7    X9  0.442853344

# 42    X7   X10 -0.552145749

# 43    X8    X9 -0.913090461

# 44    X8   X10  0.582373314

# 45    X9   X10 -0.556365998




R로 상관계수 행렬 그림을 그리는 방법은 https://rfriend.tistory.com/82 를 참고하세요. 

 

두 변수 x, y별 상관계수를 산점도로 나타낸 아래의 그림을 참조하시기 바랍니다.  상관계수가 '0'이면 '선형관계'는 없는 것이지만 '비선형관계'는 있을 수도 있음에 유의하시기 바랍니다.  두번째 그림에서 보면 상관계수가 '1'인 것은 x, y가 선으로 되어있는 관계이며, 기울기는 상관없음을 알 수 있습니다.  y 값이 '0'인 선은 상관계수 값이 없습니다.

 

 

[ Examples of correlation coefficients ]

* source : https://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient

 

 

 

상관관계(correlation) 분석할 때 인과관계(causality)와 혼동하는 경우를 종종 봅니다.  상관관계(correlation)는 단순히 두 변수 x와 y간의 상관성만을 보는 것이며, x와 y가 상관계수가 높다고 해서 x가 y의 원인이라거나 y가 x의 원인이라고 해석하면 안됩니다.

 

인과관계(causality)에는 아래처럼 6가지 종류의 인과관계가 있으며, 시간의 흐름(x chronologically precedes y), 영향을 끼치는 방향(x causally precedes y)을 함게 고려하여야 하므로 사용, 해석에 주의를 요합니다.

 

[ 6 different kinds of causality ]

 

There are six different kinds of causality within a model.

 

1. A direct causal relationship is one in which a variable, X, is a direct cause of another variable, Y (i.e. it is the immediate determinant of Y within the context of the theoretical system).

 

2. An indirect causal relationship is one in which X exerts a causal impact on Y, but only through its impact on a third variable, Z.

 

3. A spurious relationship is one in which X and Y are related, but only because of a common cause, Z.  There is no formal causal link between X and Y.

 

4. A bi-directional or reciprocal causal relationship is one in which X has a causal influence on Y, which in turn, has a causal impact on X.

 

5. An unanalyzed relationship is one in which X and Y or related, but the source of the relationship is unspecified.

 

6. A moderated causal relationship is one in which the relationship between X ad Y is moderated by a third variable.  In other words, the nature of the relationship between X and Y varies, depending on the value of Z.

 

From Jaccard, J., & Turrisi, R. (2003). Interaction Effects in Multiple Regression. Thousand Oaks, CA: Sage. 

 

* source : http://depts.washington.edu/methods/causality.html

 

 

 

위의 영어 설명을 예를 들어서 도식화하면 아래와 같습니다.

 

 

[ 인과관계의 종류 및 예시 ]

 

 

 

 

산점도, 산점도 행렬, 상관계수 행렬 그림 그리기는 아래 포스팅을 참조하시기 바랍니다.

 

ggplot2의 geom_point() 함수를 이용한 한개 변수의 산점도 그리기 

R Graphics 패키지 pairs() 함수를 사용한 산점도 행렬 그리기

corrplot 패키지를 이용한 상관계수 행렬 그림 그리기

 

많은 도움 되었기를 바랍니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 꾸욱 눌러주세요. ^^

 


728x90
반응형
Posted by Rfriend
,