이번 포스팅에서는 국가통계포털 사이트에서 받은 2020년, 2021년도 실업률과 취업자 수 통계 데이터를 가지고 R의 dplyr과 ggplot2 패키지를 사용해서 아래의 데이터 전처리 및 시각화하는 방법을 소개하겠습니다. 

 

1. 취업자 수 증가율(%) 변수 계산 (전년 동월 대비)

2. 실업률과 취업자 수 증가율 변수의 평균, 분산, 표준편차, 중앙값, 최대값, 최소값 계산

3. 실업률과 취업자 수 증가율 변수의 시계열 그래프 그리기

4. 실업률과 취업자 수 증가율 변수의  히스토그램 그리기 (히스토그램의 구간은 10개)

 

 

먼저, 국가통계포털 사이트에서 받은 2020년, 2021년도 실업률과 취업자 수 통계 데이터를 입력해서 DataFrame을 만들어보겠습니다. 데이터 자료 구조를 어떻게 해서 만드는지 유심히 봐주세요. 

 

## making a dataframe
df <- data.frame(
  month=c("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"), 
  unemploy_rate_2020=c(4.1, 4.1, 4.2, 4.2, 4.5, 4.3, 4.0, 3.1, 3.6, 3.7, 3.4, 4.1), 
  unemploy_rate_2021=c(5.7, 4.9, 4.3, 4.0, 4.0, 3.8, 3.2, 2.6, 2.7, 2.8, 2.6, 3.5), 
  employed_num_2020=c(26800, 26838, 26609, 26562, 26930, 27055, 27106, 27085, 27012, 27088, 27241, 26526), 
  employed_num_2021=c(25818, 26365, 26923, 27214, 27550, 27637, 27648, 27603, 27683, 27741, 27795, 27298)
)

print(df)
#    month unemploy_rate_2020 unemploy_rate_2021 employed_num_2020 employed_num_2021
# 1     01                4.1                5.7             26800             25818
# 2     02                4.1                4.9             26838             26365
# 3     03                4.2                4.3             26609             26923
# 4     04                4.2                4.0             26562             27214
# 5     05                4.5                4.0             26930             27550
# 6     06                4.3                3.8             27055             27637
# 7     07                4.0                3.2             27106             27648
# 8     08                3.1                2.6             27085             27603
# 9     09                3.6                2.7             27012             27683
# 10    10                3.7                2.8             27088             27741
# 11    11                3.4                2.6             27241             27795
# 12    12                4.1                3.5             26526             27298

 

 

 

1. 취업자 수 증가율(%) 변수 계산 (전년 동월 대비)

 

dplyr 패키지로 새로운 변수를 생성하는 방법은 https://rfriend.tistory.com/235 를 참고하세요. 

dplyr 패키지의 chain operation, pipe operator %>% 사용 방법은 https://rfriend.tistory.com/236 를 참고하세요. 

 

## 1. 취업자 수 증가율(%) 변수 계산 (전년 동월 대비)
library(dplyr)
df2 <- df %>% 
  transform(
    employed_inc_rate = 100*(employed_num_2021 - employed_num_2020)/employed_num_2020) # percentage


print(df2)
#    month unemploy_rate_2020 unemploy_rate_2021 employed_num_2020 employed_num_2021 employed_inc_rate
# 1     01                4.1                5.7             26800             25818         -3.664179
# 2     02                4.1                4.9             26838             26365         -1.762426
# 3     03                4.2                4.3             26609             26923          1.180052
# 4     04                4.2                4.0             26562             27214          2.454634
# 5     05                4.5                4.0             26930             27550          2.302265
# 6     06                4.3                3.8             27055             27637          2.151174
# 7     07                4.0                3.2             27106             27648          1.999557
# 8     08                3.1                2.6             27085             27603          1.912498
# 9     09                3.6                2.7             27012             27683          2.484081
# 10    10                3.7                2.8             27088             27741          2.410662
# 11    11                3.4                2.6             27241             27795          2.033699
# 12    12                4.1                3.5             26526             27298          2.910352

 

 

 

2. 실업률과 취업자 수 증가율 변수의 평균, 분산, 표준편차, 중앙값, 최대값, 최소값 계산

 

dplyr 패키지로 데이터의 요약통계량을 계산하는 방법은 https://rfriend.tistory.com/235 를 참고하세요. 

여러개의 패키지별로 그룹별 요약통계량을 계산하는 방법은 https://rfriend.tistory.com/125 를 참고하세요. 

 

## 2. 실업률과 취업자 수 증가율 변수의 평균, 분산, 표준편차, 중앙값, 최대값, 최소값 계산
df2 %>% 
  summarise(
    unemploy_rate_2021_mean = mean(unemploy_rate_2021), 
    unemploy_rate_2021_var = var(unemploy_rate_2021), 
    unemploy_rate_2021_sd = sd(unemploy_rate_2021), 
    unemploy_rate_2021_median = median(unemploy_rate_2021), 
    unemploy_rate_2021_max = max(unemploy_rate_2021), 
    unemploy_rate_2021_min = min(unemploy_rate_2021)
  )

# unemploy_rate_2021_mean unemploy_rate_2021_var unemploy_rate_2021_sd 
#                   3.675              0.9547727             0.9771247
# 
# unemploy_rate_2021_median unemploy_rate_2021_max unemploy_rate_2021_min
#                      3.65                    5.7                    2.6


df2 %>% 
  summarise(
    employed_inc_rate_mean = mean(employed_inc_rate), 
    employed_inc_rate_var = var(employed_inc_rate), 
    employed_inc_rate_sd = sd(employed_inc_rate), 
    employed_inc_rate_median = median(employed_inc_rate), 
    employed_inc_rate_max = max(employed_inc_rate), 
    employed_inc_rate_min = min(employed_inc_rate)
  )

# employed_inc_rate_mean employed_inc_rate_var employed_inc_rate_sd 
#               1.367697              3.970439             1.992596
# 
# employed_inc_rate_median employed_inc_rate_max employed_inc_rate_min
#                 2.092436              2.910352             -3.664179

 

 

3. 실업률과 취업자 수 증가율 변수의 시계열 그래프 그리기

 

ggplot2 로 시계열 그래프 그리기는 https://rfriend.tistory.com/73 를 참고하세요. 

 

## 3. 실업률과 취업자 수 증가율 변수의 시계열 그래프 그리기 
library(ggplot2)

ggplot(df2, aes(x=month, y=unemploy_rate_2021, group=1)) +
  geom_line() +
  ylim(0, max(df2$unemploy_rate_2021)) +
  ggtitle("Time Series Plot of Unemployment Rate, Year 2021")

Time Series Plot of Unemployment Rate

 

 

ggplot(df2, aes(x=month, y=employed_inc_rate, group=1)) +
  geom_line() +
  ylim(min(df2$employed_inc_rate), max(df2$employed_inc_rate)) +
  ggtitle("Time Series Plot of Employment Increase Rate, Year 2021")

Time Series Plot of Employment Increase Rate

 

 

 

4. 실업률과 취업자 수 증가율 변수의  히스토그램 그리기 (히스토그램의 구간은 10개)

 

ggplot2 패키지로 히스토그램 그리기는 https://rfriend.tistory.com/67 를 참고하세요. 

 

ggplot(df2, aes(x=employed_inc_rate)) + 
  geom_histogram(bins=10) + 
  ggtitle("Histogram of Unemployment Rate, Year 2021")

Histogram of Unemployment Rate

 

 

ggplot(df2, aes(x=employed_inc_rate)) + 
  geom_histogram(bins=10) + 
  ggtitle("Histogram of Employment Incease Rate, Year 2021")

Histogram of Employment Increase Rate

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 PostgreSQL, Greenplum database에서 SQL, MADlib 함수, PL/R, PL/Python을 사용해서 연속형 데이터에 대한 요약통계량을 구하는 방법을 소개하겠습니다.  무척 쉬운 내용이므로 쉬어가는 코너 정도로 가볍게 생각해주시면 좋겠습니다. ^^


PostgreSQL, Greenplum database 에서 연속형 데이터에 대해 그룹별로, 

(1) SQL 로 요약통계량 구하기

(2) Apache MADlib 으로 요약통계량 구하기





참고로, 이번 포스팅에서는 PostgreSQL 9.4, Greenplum 6.10.1 버전을 사용하였으며, PostgreSQL 9.4 버전보다 낮은 버전을 사용하면 최빈값(mode), 사분위부(percentile) 구하는 함수를 사용할 수 없습니다. 


먼저, 예제로 사용하기 위해 '나이'의 연속형 데이터와 '성별'의 범주형 데이터 (그룹)를 가진 간단한 테이블을 만들어보겠습니다. 결측값(missing value)도 성별 그룹별로 몇 개 넣어봤습니다. 



DROP TABLE IF EXISTS cust;

CREATE TABLE cust (id INT, age INT, gender TEXT);

INSERT INTO cust VALUES

(1,NULL,'M'),

(2,NULL,'M'),

(3,25,'M'),

(4,28,'M'),

(5,27,'M'),

(6,25,'M'),

(7,26,'M'),

(8,29,'M'),

(9,25,'M'),

(10,27,'M'),

(11,NULL,'F'),

(12,23,'F'),

(13,25,'F'),

(14,23,'F'),

(15,24,'F'),

(16,26,'F'),

(17,23,'F'),

(18,24,'F'),

(19,22,'F'),

(20,23,'F');

 




 (1) SQL로 연속형 데이터의 그룹별 요약통계량 구하기


함수가 굳이 설명을 안해도 될 정도로 간단하므로 길게 설명하지는 않겠습니다. 


표준편차 STDDEV() 와 분산 VARIANCE() 함수는 표본표준편차(sample standard deviation), 표본분산(sample variance) 를 계산해줍니다. 만약 모표준편차(population standard deviation), 모분산(population variance)를 구하고 싶으면 STDDEV_POP(), VAR_POP() 함수를 사용하면 됩니다. 


PostgreSQL 9.4 버전 이상부터 최빈값(MODE), 백분위수(Percentile) 함수가 생겨서 정렬한 후에 집계하는 기능이 매우 편리해졌습니다. (MODE(), PERCENTILE_DISC() 함수를 사용하지 않고 pure SQL로 최빈값과 백분위수를 구하려면 query 가 꽤 길어집니다.)



SELECT

    gender AS group_by_value

    , 'age' AS target_column

    , COUNT(*) AS row_count

    , COUNT(DISTINCT age) AS distinct_values

    , AVG(age)

    , VARIANCE(age)

    , STDDEV(age)

    , MIN(age)

    , PERCENTILE_DISC(0.25) WITHIN GROUP (ORDER BY age) AS first_quartile

    , MEDIAN(age)

    , PERCENTILE_DISC(0.75) WITHIN GROUP (ORDER BY age) AS third_quartile

    , MAX(age)

    , MODE() WITHIN GROUP (ORDER BY age) -- over PostgreSQL 9.4

FROM cust

WHERE age IS NOT NULL

GROUP BY gender

ORDER BY gender;





성별 그룹별로 연령(age) 칼럼의 결측값 개수를 구해보겠습니다. 

결측값 개수는 WHERE age IS NULL 로 조건절을 주고 COUNT(*)로 행의 개수를 세어주면 됩니다. 



SELECT 

    gender

    , COUNT(*) AS missing_count

FROM cust

WHERE age IS NULL

GROUP BY gender

ORDER BY gender;


Out[5]:
gendermissing_count
F1
M2





위의 집계/ 요약통계량과 결측값 개수를 하나의 조회 결과로 보려면 아래처럼 Join 을 해주면 됩니다.



WITH summary_tbl AS (
    SELECT
        gender AS group_by_value
        , 'age' AS target_column
        , COUNT(*) AS row_count
        , COUNT(DISTINCT age) AS distinct_values
        , AVG(age)
        , VARIANCE(age)
        , STDDEV(age)
        , MIN(age)
        , PERCENTILE_DISC(0.25) WITHIN GROUP (ORDER BY age) AS first_quartile
        , MEDIAN(age)
        , PERCENTILE_DISC(0.75) WITHIN GROUP (ORDER BY age) AS third_quartile
        , MAX(age)
        , MODE() WITHIN GROUP (ORDER BY age)
    FROM cust
    WHERE age IS NOT NULL
    GROUP BY gender
    ORDER BY gender
), missing_tbl AS (
    SELECT
        gender AS group_by_value
        , COUNT(*) AS missing_count
    FROM cust
    WHERE age IS NULL
    GROUP BY gender
)
SELECT a.*, b.missing_count
FROM summary_tbl a LEFT JOIN missing_tbl b USING(group_by_value)
;

 




  (2) Apache MADlib으로 연속형 데이터의 그룹별 요약통계량 구하기


Apache MADlib의 madlib.summary() 함수를 사용하면 단 몇 줄의 코드만으로 위의 (1)번에서 SQL 집계 함수를 사용해서 길게 짠 코드를 대신해서 매우 깔끔하고 간단하게 구할 수 있습니다. 


아래는 (1)번의 결과를 얻기위해 성별(gender) 연령(age) 칼럼의 집계/요약데이터를 구하는 madlib.summary() 함수 예시입니다. 


Target columns 위치에는 1 개 이상의 분석을 원하는 연속형 데이터 칼럼을 추가로 넣어주기만 하면 되므로 (1) 번의 pure SQL 대비 훨씬 편리한 측면이 있습니다! 


그리고 그룹별로 구분해서 집계/요약하고 싶으면 Grouping columns 위치에 기준 칼럼 이름을 넣어주기만 하면 되므로 역시 (1)번의 pure SQL 대비 훨씬 편리합니다!



DROP TABLE IF EXISTS cust_summary;

SELECT madlib.summary('cust'     -- Source table

                      ,'cust_summary'   -- Output table

                      , 'age'                -- Target columns

                      , 'gender'            -- Grouping columns

);






madlib.summary() 함수의 결과 테이블에서 조회할 수 있는 집계/요약통계량 칼럼 리스트는 아래와 같습니다. 



SELECT column_name

FROM INFORMATION_SCHEMA.COLUMNS

    WHERE TABLE_SCHEMA = 'public'

        AND TABLE_NAME    = 'cust_summary'

    ORDER BY ORDINAL_POSITION;

Out[7]:
column_name
group_by
group_by_value
target_column
column_number
data_type
row_count
distinct_values
missing_values
blank_values
fraction_missing
fraction_blank
positive_values
negative_values
zero_values
mean
variance
confidence_interval
min
max
first_quartile
median
third_quartile
most_frequent_values
mfv_frequencies

 



[Reference]

* PostgreSQL aggregate functions: https://www.postgresql.org/docs/9.4/functions-aggregate.html

* Apache MADlib summary function: https://madlib.apache.org/docs/v1.11/group__grp__summary.html



다음번 포스팅에서는 PostgreSQL, Greenplum에서 SQL과 Apache MADlib을 이용하여 상관계수, 상관계수 행렬을 구하는 방법(https://rfriend.tistory.com/581)을 소개하겠습니다.


이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!



728x90
반응형
Posted by Rfriend
,

일변량 연속형 자료에 대해 기술통계량(descriptive statistics)을 이용한 자료의 요약과 정리는 크게

 

- (1) 중심화 경향 (central tendency)

  : 산술평균, 중앙값, 최빈값, 기하평균, CAGR, 조화평균, 가중평균

 

- (2) 퍼짐 정도 (dispersion)

  : 분산, 표준편차, 변이계수, 범위, IQR, 백분위수

 

- (3) 분포형태와 대칭정도 (distribution)

  : 왜도, 첨도, 분위수-분위수 

 

의 3가지로 구분할 수 있습니다.

 

 

이번 포스팅에서는 일변량 연속형 자료의 (1) 중심화 경향에 대해 통계 이론과 활용 상의 주의점을 알아보고, R 함수를 가지고 예를 들어보겠습니다. 

 

일반적으로 많이 사용되는 산술평균, 중앙값, 최빈값을 먼저 살펴보겠습니다.

 

이어서 산술평균의 함정의 주의사항과 함께 기하평균, 연평균성장률, 조화평균, 가중평균을 언제 사용해야 하는지, 어떻게 계산하는지를 차례로 알아보겠습니다.

 

 

[ 산술통계량(descriptive statistics)과 R function ]

 

 산술통계

 통계량 (statistics)

R function 

 중심화 경향

(central

tendency)

 산술평균 (arithmetic mean)

 mean()

 중앙값 (median)  median()
 최빈값 (mode)

 which.max(table())

 기하평균 (geometric mean)

 prod(x)^(1/n)1/mean(1/x)

where, n = length(x)

 연평균성장률 (CAGR

 : Componded Average Growth Rate)

 (FV/IV)^(1/n)-1

where, IV : initial value of an investment
          FV : final value  of an investment
          n : investment periods

 조화평균 (harmonic mean)

 1/mean(1/x)

 가중평균 (weighted average)

 weighted.mean()

 퍼짐 정도

(dispersion)

 분산 (variance)

 var()

 표준편차 (standard deviation)  sd()

 변이계수 (coefficient of variation)

 100*sd(x)/mean(x)

 범위 (range)

 diff(range())

 IQR (Inter Quartile Range)

 IQR()

 최소값 (min)

 min()

 최대값 (max)

 max()
 백분위수(percentile)

 quantile(x, probs=c(,,,,))

 분포형태와

대칭정도

(distribution)

 왜도 (skewness)

 skewness(), fBasics package

 첨도 (kurtosis)

 kurtosis(), fBasics package

 분위수-분위수(Quantile-Quantile)

 qqnorm(), qqline(), qqplot()

※ 중심화 경향, 퍼짐 정도, 분포형태와 대칭정도의 통계량을 함께 봐야함

※ 통계량과 함께 그래프를 함께 봐야함

 

 

R 실습에는 MASS 패키지 내 Cars93 데이터의 가격(Price) 변수를 활용하겠습니다.

 

> 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 . 

 

 

아래의 Histogram, Kernel density curve plot을 보면 Price 는 왼쪽으로 치우쳐있고 오른쪽으로 꼬리가 긴 분포 형태를 띠고 있음을 알 수 있습니다.

 

> # histogram, kernel density curve > hist(Cars93$MPG.highway, freq=FALSE, breaks=30) > > hist(Cars93$Price, freq=FALSE, breaks=20) > lines(density(Cars93$Price), col="red", lty=3)

 

 

 

 

중심화 경향, 대표값으로 산술평균, 중앙값, 최빈값을 많이 사용하는데요, 모두 나름의 특징과 한계를 가지고 있습니다.  따라서 어느 하나의 통계량이 다른 통계량보다 우수하다거나 더 좋다고 말할 수는 없으며, 분석 목적, 분석 대상 자료의 특성, 업의 특성 등을 종합적으로 감안하여 조심해서 사용, 해석해야 합니다.  그리고 반드시 퍼짐 정도와 분포형태/대칭정도를 나타내는 통계량과 그래프를 병행해서 분석을 해야 왜곡된 해석을 피할 수 있습니다.  아래 개념을 정확히 이해하지 못할 경우 통계를 가지고 사기치는 지능범에게 당하는 수가 있으니 꼭 알아두어야할 기본 개념이 되겠습니다.

 

 

(1) 산술평균 (arithmetic mean, average) : mean()

 

우리들이 일반적으로 "평균"이라고 말할 때 사용하는 것이 바로 "산술평균(arithmetic mean)"입니다.  평균에는 "산술평균" 말고도 "기하평균", "조화평균", "가중평균" 등 여러 종류가 있습니다.

 

산술평균은 모집단이 정규분포를 띠고 있을 때 가장 적합한 중심화 경향 통계량이라고 할 수 있습니다.

 

달리 말하면, 분포 형태가 한쪽으로 치우쳐 있다든지, 이상값(outlier)가 있으면 영향을 크게 받으므로 사용에 주의를 요하는 통계량이라고 할 수 있습니다.  이럴 경우에는 정규분포로 변환을 하거나 이상값(outlier)를 제거한 후에 산술평균을 계산하는 것이 바람직한 조치라고 하겠습니다.

 

> # mean : mean()
> mean(Cars93$Price)
[1] 19.50968

 

 

 

(2) 중앙값 (median) : median()

 

 

중앙값은 이상치(outlier)에 덜 민감(robust)하므로 이번 예제처럼 오른쪽으로 긴 꼬리 부분에 초고가(extremely high price)의 차량이 소수 있는 경우의 분포에는 산술평균보다 더 적합한 통계량이라고 할 수 있겠습니다.

 

> # median : median()
> median(Cars93$Price)
[1] 17.7

 

 

(3) 최빈값 (mode) : which.max(table())

 

 

최빈값은 연속형 데이터를 가지고 바로 적용해서는 안되며, 사전에 범주형 데이터로 변환을 한 후에, 도수분포표(frequency distribution table)을 작성해서,  도수가 가장 많은 구간(class)을 선정하면 되겠습니다.

 

> # mode : which.max(table())
> Cars93 <- within(Cars93, {
+   Price_cd = character()
+   Price_cd[Price < 10] = "5_10"
+   Price_cd[Price >= 10 & Price < 15] = "10_15"
+   Price_cd[Price >= 15 & Price < 20] = "15_20"
+   Price_cd[Price >= 20 & Price < 25] = "20_25"
+   Price_cd[Price >= 25 & Price < 30] = "25_30"
+   Price_cd[Price >= 30 & Price < 35] = "30_35"
+   Price_cd[Price >= 35 & Price < 40] = "35_40"
+   Price_cd[Price >= 40 & Price < 45] = "40_45"
+   Price_cd[Price >= 45 & Price < 50] = "45_50"
+   Price_cd[Price >= 50 & Price < 55] = "50_55"
+   Price_cd[Price >= 55 & Price < 60] = "55_60"
+   Price_cd[Price >= 60 ] = "60_65"
+   Price_cd = factor(Price_cd, level=c("5_10", "10_15", "15_20", "20_25", "25_30", "30_35", 
+                                       "35_40", "40_45", "45_50", "50_55", "55)60", "60_65"))
+ })
> 
> table(Cars93$Price_cd)

 5_10 10_15 15_20 20_25 25_30 30_35 35_40 40_45 45_50 50_55 55)60 60_65 
   10    23    28    11     8     6     4     1     1     0     0     1 
> 
> which.max(table(Cars93$Price_cd))
15_20 
    3 

 

 

3번째 구간인 '15~20' 구간에서 도수가 28개로 가장 많이 나왔으므로, 최빈값은 '15~20' 구간이 되겠습니다.

 

===================================================== d^_^b ===================================================== 

 

아래의 기하평균, CAGR, 조화평균, 가중평균은 우리들이 일상생활에서 산술평균 대비 많이 사용하지는 않습니다만, 산술평균과 많이 헷갈리게 사용하기도 하고, 혹은 산술평균을 적용하면 안되는 상황임에도 아래의 다른 평균을 몰라서 산술평균을 잘못 적용하기도 합니다.  어떠한 상황에서 무슨 대표 통계량을 이용하는지 파악해두면 유용하겠지요?!

 

(4) 기하평균 (geometric mean) : prod(x)^(1/n), where n = length(x)

 

기하평균은 인구성장률, 투자이율과 같이 성장률 평균을 산출할 때 사용합니다. 성장률 평균 산출 시 산술평균을 사용하면 안됩니다. 복리 개념의 성장률은 면적의 개념으로 접근을 해야 하므로 기하평균을 사용하게 됩니다.

 

 

문제) 작년 이율이 1%, 올해 이율이 5%인 복리정기예금의 2년간 평균 이율은?

  • 산술평균 = (1.01 + 1.05)/2 = 1.03, 즉 3.0%  (삐이~ 잘못된 계산임)
  • 기하평균 = (1.01*1.05)^(1/2) = 1.029806, 즉 2.98% (제대로된 계산임)

 

위의 문제를 R로 풀어보면 아래와 같습니다.

 

> # geometric mean
> x <- c(1.01, 1.05) # interest rate of 1st and 2nd year
> prod(x) # 1st year rate x 2nd year rate
[1] 1.0605
> n <- length(x) # length of x vector
> 
> prod(x)^(1/n) # geometric mean
[1] 1.029806

 

 

 

(5) 연평균성장률 (CAGR : componded average growth rate) : (FV/IV)^(1/n)-1

      where, IV : initial value of an investment, FV : final value  of an investment, n : investment periods

 

 

아래 A, B라는 두 회사의 6년간의 매출액과 전년도 대비 성장률을 가지고 예를 들어보겠습니다. 

 

문제) A 회사는 2010년도 부터 해서 100억, 150억, 190억, 250억, 290억, 350억원의 매출을 올렸습니다. 

그러면 이 회사의 6년에 걸친 매출액의 연평균성장률은 얼마일까요?  매년 균등하게 몇 %씩 성장했을까요?

산술평균(arithmetic mean)으로 계산하면 29.0% 인데요, 이게 맞는 연평균성장률일까요? 땡~ 틀렸습니다. 

정답은 기하평균 개념을 적용한 CAGR 28.5% 가 되겠습니다.

 

Company B가 매년 똑같이 28.5%씩 성장한 회사인데요, 2010년도에 100억원에서 시작해서 매년 28.5%씩 성장했더니 2015년에 350억원의 매출이 되어있는 것을 확인할 수 있습니다.

 

 

예제의 CAGR을 R로 계산해보겠습니다.

 

 

> # CAGR (Compound Average Growth Rate) > IV <- c(100) # initial value of revenue > FV <- c(350) # final value of reveune > n <- c(5) # number of year > CAGR_rev <- (FV/IV)^(1/n) - 1 # CAGR > CAGR_rev [1] 0.2847352

 

 

 

 

(6) 조화평균 (harmonic mean) : 1/mean(1/x)

 

 

조화평균(harmonic mean)은 생산성, 효율 등의 평균 산출 시에 사용합니다.

 

문제) 집에서 학교까지 편도 30km 거리를 갈 때는 시속 30km/h 인 자전거를 타고 갔고, 올 때는 시속 90km/h 인 자동차를 타고 왔을 때 왕복 평균 시속은?

 

 

위 문제를 산술평균으로 풀어서 만약 (30 + 90)/2 = 60 km/h 라고 한다면, 땡~! 틀린 답입니다.

 

집과 학교 왕복거리는 총 60km 이고, 이때 걸린 시간은 집에서 학교까지 1시간 (30km거리를 시속 30km/h 로 갔으니깐), 학교에서 집으로 오는데 20분 (30km 거리를 시속 90km/h로 왔으니깐) 걸려서 총 1시간 20분이 걸렸습니다. 즉, 올바른 평균 시속은 60/1.333 = 약 45km/h 가 되겠습니다.  이 문제룰 계산할 때 사용하는 평균이 조화평균이 되겠습니다.

 

 

> # harmonic mean : 1/mean(1/x)
> km_per_hour <- c(30, 90)
> 
> arithmetic_mean <- mean(km_per_hour)
> arithmetic_mean # wrong answer
[1] 60
> 
> harmonic_mean <- 1/mean(1/km_per_hour)
> harmonic_mean # correct answer
[1] 45

 

 

 

 

(7) 가중평균 (weighted average) : weighted.mean()

 

가중평균(weighted average)은 확률, 가중치를 수반하는 평균을 산출할 때 사용합니다.

 

 

문제 1) 홍길동씨가 A, B, C 3개 회사 주식에 각각 700만원, 200만원, 100만원씩 총 1,000만원을 투자하여, 각 회사별로 투자 수익율이 15%, 9%, 5% 나왔다. 그러면 홍길동씨의 주식 투자 평균 수익률은?

 

 

산술평균으로 계산하면 0.097%이지만 이는 틀린 답입니다.  각 회사별로 주식투자한 금액의 비율(여기서는 weight) 가 서로 다르므로, 수익율에다가 투자금의 비율을 가중평균한 값 12.8%가 답이 되겠습니다.

 

R을 가지고 가중평균을 구할 때는 가중평균의 정의에 맞추어서 계산을 직접해도 되며 (아래 예제의 첫번째 경우), weighted.mean() 함수를 사용(아래 예제의 두번째 경우)해도 되겠습니다.

 

 
> # Q1
> # weighted mean
> weighted_earning_rate_1 <- (0.7*0.15 + 0.2*0.09 + 0.1*0.05)/(0.7 + 0.2 + 0.1)
> weighted_earning_rate_1
[1] 0.128
> 
> investment <- data.frame(weight=c(0.7, 0.2, 0.1), earning_rate=c(0.15, 0.09, 0.05))
> weighted_earning_rate_2 <- weighted.mean(investment$earning_rate, investment$weight)
> weighted_earning_rate_2
[1] 0.128

 

 

 

 

문제 2) 알코올 도수 9%인 와인 200ml와 알코올 도수 21%인 소주 1000ml를 섞어서 와소 폭탄주를 만들었다.  와소 폭탄주의 평균 알코올 도수는?

 

 

와소 폭탄주의 평균 알코올 도수 정답은 알코올 도수와 양을 가지고 가중평균으로 구한 19%가 되겠습니다.  

 

R에서는 가중평균의 정의에 따라서 공식에 대해서서 구할 수도 있고 (아래 예의 첫번째 경우), 아니면 weighted.mean() 함수를 사용(아래 예이 두번째 경우)해서 구해도 됩니다.

 

 
> # Q2
> weighted_alcohol_mean_1 <- (200*0.09 + 1000*0.21)/(200+1000)
> weighted_alcohol_mean_1
[1] 0.19
> 
> alcohol <- data.frame(volume=c(200, 1000), alcohol_rate=c(0.09, 0.21))
> weighted_alcohol_mean_2 <- weighted.mean(alcohol$alcohol_rate, alcohol$volume)
> weighted_alcohol_mean_2
[1] 0.19
 

 

다음번 포스팅에서는 퍼짐 정도 (dispersion) 에 대한 통계량에 대해서 소개하겠습니다.

 

중심화 경향과 퍼짐 정도가 다른 두 데이터셋을 표준화하는 방법은 아래의 포스팅을 참고하시기 바랍니다.

 

☞  R 데이터 변환 (1) 표준화 : z 표준화 변환, [0-1] 변환

 

 

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

 

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

 

 

728x90
반응형
Posted by Rfriend
,