티스토리 뷰

반응형

교차 테이블로 데이터 구조 변경



1. stack()unstack() : 비교적 간단한 구조의 변경


stack() 함수와 unstack() 함수를 사용하여 데이터 구조를 변경해보았었습니다.


> m1 <- read.csv('melt_ex.csv')

> d1 <- read.csv('dcast_ex1.csv')

> d2 <- read.csv('dcast_ex2.csv')


> head(m1)

  year mon latte americano mocha

1 2000   1   400       482   298

2 2000   2   401       483   299

3 2000   3   402       484   300

...

> head(d1)

  year  name  info value

1 2000 latte   qty   100

2 2000 mocha   qty    80

3 2000 latte price  2200

...

> head(d2)

  year      name qty price

1 2000     latte 100  1200

2 2000     mocha  80  2200

3 2000 americano 200  1000

...


# stack()함수는 모든 컬럼을 동일하게 두 개의 컬럼으로 만들어 줍니다.

> stack(m1)             # 이미 쌓여진(stacked) 컬럼(year, mon)까지 모두 stack 처리해버립니다.    

    values       ind           컬럼 고정 불가. (스택 처리를 하지 않아도 되는 컬럼 제외 불가)

1     2000      year          

2     2000      year

...

25       1       mon

26       2       mon

...

49     400     latte

50     401     latte

...

73     482 americano

...

97     298     mocha

98     299     mocha

...




2. reshape2::melt()reshape2::dcast() : (다양한 옵션을 사용하여)교차 테이블 만들기 중요@@@


데이터의 모양을 바꾸거나 그룹별 요약 값을 계산하는 함수들을 담고 있는 패키지

> install.packages('reshape2') 

> library(reshape2)


2-1) melt : stack()함수처럼 동일 관측치의 값이 각 컬럼으로 분리되어 있는 경우 차곡차곡 쌓는 형식입니다.


  melt()함수는 stack()함수와 달리 일부 컬럼 고정(제외) 나머지 컬럼을 stack 처리할 수 있는 것이 melt 함수의 특징입니다. 

주로 Join, group by에서 그룹 연산을 위해 주로 사용합니다.


melt(data,   # 원본 데이터

     id,        # 고정 컬럼

     measure.var)   # stack처리 할 컬럼(생략 시 id컬럼 제외 모든 컬럼)


> library(reshape2)

> head(m1)

  year mon latte americano mocha

1 2000   1   400       482   298

2 2000   2   401       483   299

3 2000   3   402       484   300

...

> melt_d1 <- melt(m1, id=c('year','mon'))   # year, mon 컬럼을 제외하고 stack 처리

> melt_d1[order(melt_d1$year, melt_d1$mon),]  # 함수 결과를 year, mon 순으로 정렬

   year mon  variable value

1  2000   1     latte   400

25 2000   1 americano   482

...

4  2000   4     latte   403

28 2000   4 americano   485

...

10 2000  10     latte   409

34 2000  10 americano   491

...

36 2000  12 americano   493

60 2000  12     mocha   309

...

37 2001   1 americano   494

61 2001   1     mocha   310

...

22 2001  10     latte   421

46 2001  10 americano   503

...

47 2001  11 americano   504

71 2001  11     mocha   320

...

> head(m1)

  year mon latte americano mocha

1 2000   1   400       482   298

2 2000   2   401       483   299

3 2000   3   402       484   300

...

> melt(m1, id=c('year','mon'), measure.vars = 'latte')   # latte 데이터만 stack 처리

   year mon variable value

1  2000   1    latte   400

2  2000   2    latte   401

...

11 2000  11    latte   410

12 2000  12    latte   411

13 2001   1    latte   412

14 2001   2    latte   413

15 2001   3    latte   414

...

23 2001  11    latte   422

24 2001  12    latte   423



2-2) dcast : unstack 함수처럼 이미 쌓여진(stacked) 컬럼을 각 항목별로 분리하기 위해 사용합니다.


  그래프 작성, 분석, 시각화에 필요한 교차 테이블 작성이 가능합니다. 각 row와 column을 지정 가능하고, 품목별 가격, 품목별 수량 과 같이 표현할 수 있습니다.


dcast(data,             # 원본 데이터 

      formula,             # 행 고정 ~ unstack 처리 컬럼

      fun.aggregate = NULL,      # 데이터 축약 시 사용 (그룹,결합)함수(default:length)  

      margins = NULL,         # 부분합 출력 시 TRUE

      value.var = guess_value(data))   # value 컬럼 지정(분리 할 컬럼), 생략 가능, 생략 시 마지막 컬럼 지정


# 의미없이 쌓여진 컬럼을 서로 다른 각 컬럼으로 분리합니다.

> head(d1)

  year  name  info value

1 2000 latte   qty   100

2 2000 mocha   qty    80

3 2000 latte price  2200

...

# 품목별 price와 qty 교차 테이블 

# 고정시키고자하는 컬럼(name), 분리 컬럼(info), 값을 담고자하는 대상(value)

> dcast(d1, name ~ info)    # 맨 마지막 컬럼(value)을 자동으로 지정 

   name price qty

1 latte  2200 100

2 mocha  2500  80  


# d1 데이터로 년도별 price와 qty의 총 합을 나타내는 교차 테이블 (하나의 쉘에 다수에 값이 포함될 경우 그룹 함수가 필요)

> dcast(d1, year ~ info)      # 데이터 축약 발생 시 default로 데이터의 수 출력

Aggregation function missing: defaulting to length

  year price qty

1 2000     2   2

> dcast(d1, year ~ info, fun.aggregate = sum)

  year price qty

1 2000  4700 180


# d2 데이터로 년도별, 품목별 교차 테이블 작성

> head(d2)

  year      name qty price

1 2000     latte 100  1200

2 2000     mocha  80  2200

3 2000 americano 200  1000

> dcast(d2, year ~ name)    # value.var 생략 시 자동으로 마지막 컬럼 선택

Using price as value column: use value.var to override.

  year americano latte mocha

1 2000      1000  1200  2200

2 2001      1100  1250  2300

> dcast(d2, year ~ name, value.var = 'qty')   # 단점: 종종 컬럼 지정 시 '따움표가 필요할 떄가 있음..

  year americano latte mocha

1 2000       200   100    80

2 2001       210   120    70


# 행별, 열별 부분합 출력

> dcast(d2, year ~ name, margins = TRUE)   # margins 사용 시 그룹 함수 지정 필요, 생략 시 데이터의 수 출력

Using price as value column: use value.var to override.

Aggregation function missing: defaulting to length

   year americano latte mocha (all)

1  2000         1     1     1     3

2  2001         1     1     1     3

3 (all)         2     2     2     6

> dcast(d2, year ~ name, margins = TRUE, fun.aggregate = sum)    # 부분합으로 주로 sum 사용

Using price as value column: use value.var to override.

   year americano latte mocha (all)

1  2000      1000  1200  2200  4400

2  2001      1100  1250  2300  4650

3 (all)      2100  2450  4500  9050


# 참고 : dcast의 포뮬러에 컬러 추가 

# dcast의 formula에 고정 대상을 + 로 추가 가능

> sales <- read.csv("sales.csv", stringsAsFactors = F)

> sales

         날짜 지점   품목 판매량

1  2018-01-01   c1 냉장고    899

2  2018-01-01   c1     TV    859

...

15 2018-01-02   c1 세탁기    234

16 2018-01-02   c1 에어컨    645

...

28 2018-01-03   c1 에어컨    493

29 2018-01-03   c2 냉장고    457

...

35 2018-01-03   c2 세탁기    453

36 2018-01-03   c2 에어컨    234


> library(reshape2)

> dcast(sales, 날짜 ~ 품목, fun.aggregate = sum)        # 날짜별, 품목 판매량 교차 테이블

Using 판매량 as value column: use value.var to override.

        날짜   TV 냉장고 세탁기 에어컨

1 2018-01-01 2236   2588   1189   2114

2 2018-01-02 1144   1642   1733   1556

3 2018-01-03 1554   1536   1142   1362

> dcast(sales, 날짜 + 지점 ~ 품목, fun.aggregate = sum)   # 날짜+지점별, 품목 판매량 교차 테이블

Using 판매량 as value column: use value.var to override.

        날짜 지점   TV 냉장고 세탁기 에어컨

1 2018-01-01   c1  859    899    453    400

2 2018-01-01   c2 1377   1689    736   1714

3 2018-01-02   c1  345    565    234    645

4 2018-01-02   c2  799   1077   1499    911

5 2018-01-03   c1  454    845    545    493

6 2018-01-03   c2 1100    691    597    869

> dcast(sales, 날짜 ~ 지점 + 품목, fun.aggregate = sum)   # 날짜별, 지점+품목 판매량 교차 테이블 

Using 판매량 as value column: use value.var to override.  

        날짜 c1_TV c1_냉장고 c1_세탁기 c1_에어컨 c2_TV c2_냉장고 c2_세탁기 c2_에어컨

1 2018-01-01   859       899       453       400  1377      1689       736      1714

2 2018-01-02   345       565       234       645   799      1077      1499       911

3 2018-01-03   454       845       545       493  1100       691       597       869

파이썬에서는 멀티컬럼으로 출력 가능하지만 R에서는 멀티컬럼이 불가하여 컬럼을 자동으로 결합하여 컬럼화합니다.

  고로, R에서는 잘 사용되지 않음 (파이썬은 상하위 레벨 정리가 가능)



Q. deep

# melt, dcast 심화 문제 

# 1. 상반기사원별월별실적현황_new.csv 파일을 읽고 

> emp_result <- read.csv("상반기사원별월별실적현황_new.csv", stringsAsFactors = F)

> str(emp_result)

> head(emp_result)

    이름 월 실적금액 목표금액 성취도

1 박동주  1      100      100   1.00

2 박동주  2       85      100   0.85

3 박동주  3       75      100   0.75

4 박동주  4       98      100   0.98

5 박동주  5       92      100   0.92

6 박동주  6       97      100   0.97


# 각 사원별 월별 성취율의 비교하기위해 아래와 같은 교차테이블 형태로 변경

#       1     2     3     4     5     6

#박동주 1     0.85 0.75  0.98  0.92  0.97

#최경우 0.90 0.92  0.68  0.87  0.89  0.89  

> library(reshape2)

> res1 <- dcast(emp_result, 이름 ~ 월)

Using 성취도 as value column: use value.var to override.

> rownames(res1) <- res1$이름     # 이름을 행 번호로

> res1 <- res1[,-1]

> res1

          1    2    3    4    5    6

김지수 0.78 0.86 1.00 0.91 0.95 0.91

박동주 1.00 0.85 0.75 0.98 0.92 0.97

박지영 0.70 0.97 1.10 0.86 0.90 0.79

윤정웅 0.95 1.01 0.89 0.85 0.79 0.89

이동근 0.92 0.83 0.79 0.96 0.79 0.95

주시현 0.85 0.91 0.97 0.69 0.87 0.86

최경우 0.90 0.92 0.68 0.87 0.89 0.89


############################################################


#2. sales.csv 파일을 읽고

> sales <- read.csv("sales.csv", stringsAsFactors = F)

> str(sales)

> head(sales)

        날짜 지점   품목 판매량

1 2018-01-01   c1 냉장고    899

2 2018-01-01   c1     TV    859

3 2018-01-01   c1 세탁기    453

4 2018-01-01   c1 에어컨    400

5 2018-01-01   c2 냉장고    695

6 2018-01-01   c2     TV    920


#1) 지점별 품목별 판매량의 요약 정보 출력

> dcast(sales, 지점 ~ 품목, fun.aggregate = sum)       # 그룹함수의 결과를 표현하기 위해 fun.aggregate 옵션 필요

Using 판매량 as value column: use value.var to override.

  지점   TV 냉장고 세탁기 에어컨

1   c1 1658   2309   1232   1538

2   c2 3276   3457   2832   3494    


#2) 날짜별 각 품목별 판매량의 총합 출력

> dcast(sales, 날짜 ~ 품목, fun.aggregate = sum)

Using 판매량 as value column: use value.var to override.

        날짜   TV 냉장고 세탁기 에어컨

1 2018-01-01 2236   2588   1189   2114

2 2018-01-02 1144   1642   1733   1556

3 2018-01-03 1554   1536   1142   1362


###########################################################


#3. 연령별실업률_40~49세.csv 파일을 읽고

> unemp <- read.csv("연령별실업율_40-49세.csv", stringsAsFactors = F)

> str(unemp)

> unemp

  월 X2014년 X2015년 X2016년 X2017년 X2018년

1  1     4.0     4.3     2.4     2.0     2.2

2  2     4.5     4.5     2.5     2.1     2.6

3  3     3.9     4.1     2.5     2.2     2.8

4  4     3.6     3.3     2.1     2.1     2.3

5  5     3.4     2.7     2.0     2.2     2.2

6  6     3.3     2.4     1.8     2.2     2.0

...

> popul <- read.csv("data.csv", stringsAsFactors = F)

> str(popul)

> popul

   년도 월 총구직자수

1  2014  1       7228

2  2014  2       8888

...

22 2015 10       9412

23 2015 11       7708

...

33 2016  9       8434

34 2016 10       5171

...

46 2017 10       6464

47 2017 11       5106

...

59 2018 11       6791

60 2018 12       7534


#1) 각 년도별 실업자 수의 총 합 출력

#(실업자/총구직인구 * 100 = 실업률)

#(단, 각 날짜별 총구직인구는 data.csv파일에 있다)

> library(stringr)

> colnames(unemp)[-1] <- substr(colnames(unemp)[-1],2,5)  # 컬럼명 먼저 변경 ('x2018' -> '2008')

> library(reshape2)

> unemp2 <- melt(unemp, '월')   # 월 기준으로 stack

> unemp2

   월 variable value

1   1     2014   4.0

2   2     2014   4.5

...

15  3     2015   4.1

...

27  3     2016   2.5

...

39  3     2017   2.2

...

53  5     2018   2.2

...

> result <- merge(popul, unemp2, by.x = c('년도','월'), by.y = c('variable','월'))  # 데이터 조인

> result

   년도 월 총구직자수 value

1  2014  1       7228   4.0

...

13 2015  1       8051   4.3

...

30 2016  3       9623   2.5

...

41 2017  2       5637   2.1

...

54 2018  3       6732   2.8

...

> result$실업자수 <- round(result$총구직자수 * result$value / 100)    # 실업자 수 연산 후 컬럼에 추가 


> aggregate(실업자수 ~ 년도, result, sum)   # 연도별 실업자 수의 합 (aggregate 사용)

  년도 실업자수

1 2014     3161

2 2015     2796

3 2016     1844

4 2017     1874

5 2018     1965

> library(plyr)

> ddply(result, .(년도), summarise, sum=sum(실업자수))   # 연도별 실업자 수의 합 (ddply 사용)

  년도  sum

1 2014 3161

2 2015 2796

3 2016 1844

4 2017 1874

5 2018 1965





참고: KIC 캠퍼스 머신러닝기반의 빅데이터분석 양성과정

반응형
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday