R-Studio 전처리 dcast/melt 사용하기

R-Studio의 전처리함수 dcast/melt 함수.

Featured image

R-Studio 도 함수를 만들 수 있다.

전처리를 위해 reshape2 패키지를 이용 한다.

사용된 함수

함수이름
dcast() / melt()

파일 소스

우클릭 -> 다른이름으로 링크저장 이용해 주세요
examtest.csv
data.csv
wide.csv
students.csv
fruits_10.csv
pay_data.csv

사용 예시 소스코드

install.packages("reshape2")
library(reshape2)

mytest <- read.csv("examtest.csv", header = T)
mytest
#       names gender korean english math computer science
# 1    강감찬      M     85      77   80      100      96
# 2    이순신      M     86      90   82       93      93
# 3  신사임당      F     80      98   87       92      90
# 4    서현진      F     97      87   80       85      80
# 5    전지현      F    100     100   98      100      94
# 6    김유신      M     56      58   80       92      60
# 7  을지문덕      M     88      88   90       79      87
# 8    이효리      F     48      59   60       50      54
# 9      김구      M     70      66   70       80      73
# 10   안중근      M     40      92   56       40      45
# 11   황신혜      F     46      76   79       46      50
# 12     계백      M     58      88   62       58      60
# 13   황진이      F     78      89   80       76      71
# 14   김고은      F     77      80   70       78      73
# 15   이만기      M     79      82   88       80      78
# 16   이상순      M     95      89   89       90      97
# 17   박보검      M     97      94   88       90      91
# 18   김완선      F     86      90   86       80      88
# 19   고현정      F     60      77   81       80      70
# 20   노사연      F     87      86   76       78      76

# 원 데이터 40행 7열
str(mytest)
# 'data.frame':	20 obs. of  7 variables:
#   $ names   : Factor w/ 20 levels "강감찬","계백",..: 1 16 11 10 18 7 13 17 5 12 ...
# $ gender  : Factor w/ 2 levels "F","M": 2 2 1 1 1 2 2 1 2 2 ...
# $ korean  : int  85 86 80 97 100 56 88 48 70 40 ...
# $ english : int  77 90 98 87 100 58 88 59 66 92 ...
# $ math    : int  80 82 87 80 98 80 90 60 70 56 ...
# $ computer: int  100 93 92 85 100 92 79 50 80 40 ...
# $ science : int  96 93 90 80 94 60 87 54 73 45 ...

# names와 gender를 보존하고 나머지를 var과 val 컬럼으로 녹아 들어간다(합쳐진다)
# korean english math computer science 컬럼이 variable과 value 로 합쳐 지기 때문에
# 원 데이터가 20행 이고 5열 이었기 떄문에 20*5 100행 4열이 된다.
# 100행 4열이 된다.
meltdata <- melt(mytest, id=c("names", "gender"))
str(meltdata)
# 'data.frame':	100 obs. of  4 variables:
#   $ names   : Factor w/ 20 levels "강감찬","계백",..: 1 16 11 10 18 7 13 17 5 12 ...
# $ gender  : Factor w/ 2 levels "F","M": 2 2 1 1 1 2 2 1 2 2 ...
# $ variable: Factor w/ 5 levels "korean","english",..: 1 1 1 1 1 1 1 1 1 1 ...
# $ value   : int  85 86 80 97 100 56 88 48 70 40 ...

# names를 보존하고 english 컬럼과 math 컬럼의 Value 값만 출력하라.
newMelt <- melt(mytest, id=c("names"), measure=c("english", "math"))
str(newMelt)
# 'data.frame':	40 obs. of  3 variables:
#   $ names   : Factor w/ 20 levels "강감찬","계백",..: 1 16 11 10 18 7 13 17 5 12 ...
# $ variable: Factor w/ 2 levels "english","math": 1 1 1 1 1 1 1 1 1 1 ...
# $ value   : int  77 90 98 87 100 58 88 59 66 92 ...

data <- read.csv("data.csv", header = T)
data
# 'data.frame':	11 obs. of  3 variables:
#   $ 날짜    : Factor w/ 3 levels "01-01","01-02",..: 1 1 2 1 1 3 2 2 3 3 ...
# $ 이름    : Factor w/ 4 levels "강감찬","김완선",..: 1 3 1 3 1 3 2 4 1 3 ...
# $ 구매수량: int  3 4 2 3 2 3 6 1 5 1 ...

# formula : 행1 + 행2 ~ 열1 + 열2
# data를 행에 이름으로 그룹핑하고 열은 날짜로 나열 하는데. 구매수량 컬럼은 더하라.
widedata <- dcast(data, 이름 ~ 날짜, sum, value.var="구매수량")
widedata
# 왼쪽 -> 오른쪽으로 바뀐다.
#     날짜   이름 구매수량            # 이름 01-01 01-02 01-03
# 1  01-01 강감찬        3        # 1 강감찬     5     2     5
# 2  01-01 심수봉        4        # 2 김완선     0     6     8
# 3  01-02 강감찬        2        # 3 심수봉     7     0     4
# 4  01-01 심수봉        3        # 4 이봉원     0     1     0
# 5  01-01 강감찬        2
# 6  01-03 심수봉        3
# 7  01-02 김완선        6
# 8  01-02 이봉원        1
# 9  01-03 강감찬        5
# 10 01-03 심수봉        1
# 11 01-03 김완선        8

# 바뀐 파일 출력 저장
write.csv(widedata, "wide.csv", row.names=F)

newWide <- read.csv("wide.csv")
# 컬럼 이름 바꾸기
colnames(newWide) <- c("이름", "1월1일", "1월2일", "1월3일")
newWide
#     이름 1월1일 1월2일 1월3일
# 1 강감찬      5      2      5
# 2 김완선      0      6      8
# 3 심수봉      7      0      4
# 4 이봉원      0      1      0

long <- melt(newWide, id="이름")
colnames(long) <- c("이름", "날짜", "구매수량")
str(long)
# 'data.frame':	12 obs. of  3 variables:
#   $ 이름    : Factor w/ 4 levels "강감찬","김완선",..: 1 2 3 4 1 2 3 4 1 2 ...
# $ 날짜    : Factor w/ 3 levels "1월1일","1월2일",..: 1 1 1 1 2 2 2 2 3 3 ...
# $ 구매수량: int  5 0 7 0 2 6 0 1 5 8 ...
long
#      이름   날짜 구매수량
# 1  강감찬 1월1일        5
# 2  김완선 1월1일        0
# 3  심수봉 1월1일        7
# 4  이봉원 1월1일        0
# 5  강감찬 1월2일        2
# 6  김완선 1월2일        6
# 7  심수봉 1월2일        0
# 8  이봉원 1월2일        1
# 9  강감찬 1월3일        5
# 10 김완선 1월3일        8
# 11 심수봉 1월3일        4
# 12 이봉원 1월3일        0

# students.csv 파일을 읽어서 1~2번째 컬럼만 남기고, 길게 펼쳐보세요.
stu <- read.csv("students.csv")
stu
#   subject time age weight height
# 1  김철수    1  33     90   1.87
# 2  박영희    1  NA     NA   1.54

# newMelt02 <- melt(stu, id=c("subject", "time"))
newMelt02 <- melt(stu, id=c(1:2))
newMelt02
#   subject time variable value
# 1  김철수    1      age 33.00
# 2  박영희    1      age    NA
# 3  김철수    1   weight 90.00
# 4  박영희    1   weight    NA
# 5  김철수    1   height  1.87
# 6  박영희    1   height  1.54

fruits <- read.csv("fruits_10.csv")
str(fruits)
# 'data.frame':	12 obs. of  4 variables:
# $ year : int  2000 2000 2000 2000 2001 2001 2001 2001 2002 2002 ...
# $ name : Factor w/ 4 levels "apple","banana",..: 1 2 4 3 1 2 4 3 1 2 ...
# $ qty  : int  6 2 7 9 10 7 3 15 13 10 ...
# $ price: int  6000 1000 3500 900 10000 3500 1500 1500 13000 5000 ...

# year만 남기고, 나머지를 아래로 길게
fruitMelt <- melt(fruits, id="year")
str(fruitMelt)
# 'data.frame':	36 obs. of  3 variables:
# $ year    : int  2000 2000 2000 2000 2001 2001 2001 2001 2002 2002 ...
# $ variable: Factor w/ 3 levels "name","qty","price": 1 1 1 1 1 1 1 1 1 1 ...
# $ value   : chr  "apple" "banana" "peach" "berry" ...

# year와 name만 남기고 행 나열
fruitMelt <- melt(fruits, id=c(1:2))
str(fruitMelt)
# 'data.frame':	24 obs. of  4 variables:
# $ year    : int  2000 2000 2000 2000 2001 2001 2001 2001 2002 2002 ...
# $ name    : Factor w/ 4 levels "apple","banana",..: 1 2 4 3 1 2 4 3 1 2 ...
# $ variable: Factor w/ 2 levels "qty","price": 1 1 1 1 1 1 1 1 1 1 ...
# $ value   : int  6 2 7 9 10 7 3 15 13 10 ...

# 파생 칼럼 이름을 디폴트 값으로 안하고 사용자지정으로 바꿈.
mTest <- melt(fruits, id=c(1:2), variable.name = "asdf", value.name = "qwert")
str(mTest)
# 'data.frame':	24 obs. of  4 variables:
# $ year : int  2000 2000 2000 2000 2001 2001 2001 2001 2002 2002 ...
# $ name : Factor w/ 4 levels "apple","banana",..: 1 2 4 3 1 2 4 3 1 2 ...
# $ asdf : Factor w/ 2 levels "qty","price": 1 1 1 1 1 1 1 1 1 1 ...
# $ qwert: int  6 2 7 9 10 7 3 15 13 10 ...

# melt 를 다시 반대로 분류함.
# ~ 이전 까지의 컬럼 들을 행으로 따로 분류하고 ~ 이후의 컬럼 열로 분류
dcast(mTest, year + name ~ asdf)
#    year   name qty price
# 1  2000  apple   6  6000
# 2  2000 banana   2  1000
# 3  2000  berry   9   900
# 4  2000  peach   7  3500
# 5  2001  apple  10 10000
# 6  2001 banana   7  3500
# 7  2001  berry  15  1500
# 8  2001  peach   3  1500
# 9  2002  apple  13 13000
# 10 2002 banana  10  5000
# 11 2002  berry  11  1100
# 12 2002  peach   5  2500

# subset 함수는 plyr 패키지가 필요하다.
library("plyr")
# subset 으로 apple 대한 행만 추출 한다.
dcast(mTest, year ~ asdf, sum, subset=.(name == "apple"))
  # year qty price
# 1 2000   6  6000
# 2 2001  10 10000
# 3 2002  13 13000

# 논리 연산자 를 이용한 dcast
dcast(mTest, year ~ asdf, sum, subset=.(name=="apple" | name=="banana"))
#   year qty price
# 1 2000   8  7000
# 2 2001  17 13500
# 3 2002  23 18000

# pay_data.csv 를 불러오기기, header 있음.
pay_data <- read.csv("pay_data.csv", header = T)
str(pay_data)
# 'data.frame':	24 obs. of  4 variables:
# $ user_id     : Factor w/ 2 levels "김철수","박영희": 1 1 1 1 1 1 1 1 1 1 ...
# $ product_type: Factor w/ 2 levels "사과","포도": 1 1 1 1 1 1 2 2 2 2 ...
# $ pay_method  : Factor w/ 3 levels "신용카드","직불카드",..: 3 2 3 2 1 1 3 2 3 2 ...
# $ price       : int  1000 2000 3000 4000 6000 5000 3000 2000 4000 7000 ...

# 고객별 상품 유형에 따른구매 금액의 총합
result <- dcast(pay_data, user_id ~ product_type, sum, value.var = "price", na.rm = T)
result
#   user_id  사과  포도
# 1  김철수 21000 19000
# 2  박영희 23000 20000

# 행 :고객유형, 상품유형 / 열 : 지불 방법
# ~ 전에는 행으로 나열 하고 ~ 후에는 열로 나열 하는데 price 부분은 지불 방법에 따라
# 종류가 나뉘기 때문에 지불 방법을 기준으로 price는 합쳐야 한다 그러므로 sum을쓰고 그 타겟은 price이다.
# NA 값은 거른다.
result01 <- dcast(pay_data, user_id + product_type ~ pay_method, sum, value.var = "price", na.rm = T)
result01
#   user_id product_type 신용카드 직불카드 현금
# 1  김철수         사과    11000     6000 4000
# 2  김철수         포도     3000     9000 7000
# 3  박영희         사과    10000     6000 7000
# 4  박영희         포도     6000     8000 6000

# 고객 유형별 지불 방법에 따른 구매 금액의 총합
result02 <- dcast(pay_data, user_id ~ pay_method, sum, value.var = "price", na.rm = T)
result02
#   user_id 신용카드 직불카드  현금
# 1  김철수    14000    15000 11000
# 2  박영희    16000    14000 13000

# 행 :고객유형, 열 : 상품유형, 지불방법
result03 <- dcast(pay_data, user_id ~ product_type+pay_method, sum, value.var = "price", na.rm = T)
result03
#   user_id 사과_신용카드 사과_직불카드 사과_현금 포도_신용카드 포도_직불카드 포도_현금
# 1  김철수         11000          6000      4000          3000          9000      7000
# 2  박영희         10000          6000      7000          6000          8000      6000