Recent Posts
Recent Comments
Link
Today
Total
03-11 06:38
관리 메뉴

Hippo's data

R 기본문법 정리 - 2 본문

R

R 기본문법 정리 - 2

Hippo's data 2023. 9. 4. 00:08
728x90

. 현재작업공간 ./를 통해 표시

rm(list=ls()) - 나머지 다 날리고 함수만 실행시 정상적으로 실행되는지 확인

gc()

--------------------------9 데이터 읽고 쓰기

작업 디렉토리(working directory)

setwd() 함수 – 경로설정시 \하나일시 \\두개로 바꿔주거나 /하나로 바꿔줌(“ “씌움) 혹은 r“( ~~~경로~~~)”로 바꿔줌

getwd() 함수 - 현재 설정된 작업 디렉토리를 확인

 

txt 파일 읽기

흔히 메모장에 작성된 파일(확장자명이 .txt)이라고 생각하면 됨.

read.table() 함수 - txt파일을 R에서 불러오기

-file : 불러올 데이터 (경로 + 파일이름.txt)

-header : 데이터에 열(변수) 이름이 있는지 여부/ T - 첫행을 변수이름으로 사용(기본값) / F – 열이름없이 첫행부터 데이터로 인식

-sep : 데이터 값을 구분할 구분자. 기본 값은 공백 (””)

-skip : 데이터를 읽기 전 생략할 줄 수 – 윗부분에 설명 써진 데이터 읽을 필요 없을 때 생략

 

read.table("txt\\text data1.txt")

read.table("./txt/text data1.txt") ./(점 슬래쉬)- 현재 경로 (더 명확하게 표기한 것) 탭키로 자동완성 가능

read.table("./txt/text data1.txt", sep=",", header = T) – 구분자가 ,일경우 , 입력

no name age

1 1 Hong 30

2 2 Chul 25

3 3 Young 21

read.table("./txt/text data2.txt", sep="t", header = T) – 구분자가 일경우 \t 입력

read.table("./txt/text data3.txt", sep=" ", header = T)- 구분자가 띄어쓰기일경우 띄어쓰기해줌

read.table("./txt/text data4.txt", sep=" “ , header = T,skip = 3 ) – 스킵함수 이용

 

csv 파일 읽기 – txt와 똑같이 사용 (단지 구분자가 항상 ,콤마로 되어있음)

csv파일은 R에서 read.table() 함수를 사용해 불러올 수 있고 특별히 csv 파일을 읽는 read.csv() 함수가 존재함.

read.csv() 함수는 read.table() 함수를 사용하고 default로 설정된 인자만 다름.

엑셀 파일 읽기

엑셀파일(확장자명 : .xlsx)은 csv 파일과 더불어 널리 사용되는 데이터 저장 방식임.

패키지를 사용하지 않고 엑셀 파일을 불러오기 위해서는 엑셀파일을 열고 csv파일로 다시 저장하면 됨.

엑셀파일을 읽기 위해서는 readxl 패키지를 설치 후 불러온 후,

read_xlsx() 함수를 사용해 읽을 수 있음.

패키지 설치 및 불러오기

인터넷 가능한 환경에서 R콘솔(혹은 스크립트)창에서 install.packages(”패키지 이름”)을 실행하면 됨.

패키지가 정상적으로 설치되었다면 library(패키지 이름) 또는 require(패키지 이름)으로 패키지를 불러올 수 있음.

read_xlsx() 함수

path : 불러올 데이터 (경로 + 파일이름.xlsx)

sheet : 정수를 입력하면 불러올 sheet의 위치, 문자형 이름을 입력하면 해당 sheet 이름에 해당하는 데이터를 불러옴.

col_names : T- 첫번째 행을 변수 이름으로 사용 – header 인자와 같은 역할

skip : 데이터를 읽기 전 생략할 줄 수

 

# A tibble: 3 x 3 - tibble- 데이터프레임보다 적은 메모리사용하여 저장

no name age - as.data.frame( )으로 형태 바꿔서 사용

<dbl> <chr> <dbl>

1 1 Hong 30

2 2 Chul 25

3 3 Young 21

 

SAS와 SPSS 파일 읽기 - 통계분석프로그램

haven 패키지의 read sas()와 read spss() 함수를 이용하여 R에서 불러올 수 있음.

read_sas() 함수 - read spss() 함수도 유사

data file : 불러올 SAS 데이터셋 (경로 + 파일이름.sas7bdat)

read_sas("./sas/sas_data.sas7bdat")

URL을 통한 데이터 불러오기

web사이트에 데이터가 업로드 되어있는 경우 업로드된 url을 통해 데이터를 불러올 수 있음.

오른쪽마우스- 다른이름으로 저장- 데이터형태 저장하여 읽을 수도 있음

url<-"http://www.stats.ox.ac.uk/pub/datasets/csb/ch11b.dat"

read.table(url)

 

RData 불러오기

다른 데이터 형식 보다 R에서 데이터를 저장 및 읽는 속도가 빨라 큰 데이터를 저장하거나 내보낼 때 유용하며 R 객체 자체를 저장하기 때문에 객체의 데이터 종류가 변경되거나 하는 문제가 발생하지 않음. (csv 포맷으로 변환하여 읽는것보다 훨씬 빠른 처리) (R사용자끼리만 데이터주고받을수있음)

load()  변수그자체를 저장(테이블 형식으로 저장X)

load("./Rdata/rdata.RData") - 작업디렉터리 설정된 상태에서 탭키

rdata_data - 변수안 데이터 불러옴

 

fread() 함수

data.table 패키지에서 제공해주는 함수로 큰 크기의 파일을 빠르게 읽을 수 있음.

보통 fread() 함수는 큰 크기의 텍스트 파일 혹은 csv 파일을 읽는데 사용함

input or file : 불러올 데이터 (경로 + 파일이름.txt 또는 .csv) – 구분자 자동으로 찾아서 적용(sep인자 필요없음), header인자 자동으로 찾아서 읽어줌

class(fread("./txt/text data1.txt")) - 클래스 확인

[1] "data.table" "data.frame" - 데이터 테이블 클래스 존재

as.data.frame( )형식으로 바꿔서 작업 - data.table형식 잘 모르기 때문

 

데이터 쓰기

write.csv() 함수 - R에서 csv로 내보냄

x : R 객체, 보통 행렬이나 데이터 프레임 / 행렬이나 데이터 프레임이 아닌 경우 데이터 프레임으로 만든 후 내보냄.

file : 문자형으로 내보낼 파일 이름을 입력(경로 + 파일 이름 + 확장자).

temp <-read.csv("./csv/csv data.csv", header = T)

temp$age[1]<-28

write.csv(temp, file = "./csv/csv_data2.csv") – 수정후 이름새로붙여서 내보냄

write.table() 함수 – 텍스트파일로 내보냄

 

RData로 데이터 쓰기

R 사용자간의 데이터를 주고 받거나 R에서 계속 처리해야할 데이터라면 굳이 csv로 내보내기 보다(csv내보내려면 데이터프레임형식변환 필요)는 RData로 데이터를 저장하는 것이 효율적임.

또한 csv 파일로 저장하기 힘든 구조를 가진 데이터들 (예를 들어 리스트 객체)도 저장이 가능.

save() 함수는 객체를 선택적으로 저장 – 콤마로 구분하며 변수저장

save(변수, 변수, 변수, 변수, 변수 , file= 저장위치, 파일이름지정, 확장자 )

save(temp, x, file = "./Rdata/rdata2.Rdata") – 윈도우-확장자R대소문자 구분X / 리눅스, 맥 –대소문자구분

save.image() 함수는 현재 전역 변수로 선언된 모든 변수를 저장함.

save.image(file = 저장위치, 파일이름지정, 확장자)

save.image(file = "./Rdata/rdata3.Rdata")

 

응용 - 실습

csv- 컴마로 구분 / tsv – 탭으로 구분 sep = “\t

sprintf("%s + %s",1,2) - c스타일로 문자처리하는 방법 , 입력된 값 붙여줌

[1] "1 + 2" - 1은 첫번째 %s로 2는 두번째 %s로 반환

sprintf("%s / %s", 1,3) [1] "1 / 3"

%s - string 문자 자동으로 문자로 바껴서 입력됨

%f - float 실수 기본으로 소수점뒤 여섯자리까지 표기

%d - 정수로 반환 뒤 소수점 잘림

모든 숫자는 문자로 표현 가능하므로 기본적으로 %s 주로 사용

 

path="." - 현재 작업공간

subdir1 = "daily"

subdir2 = "dpu"

subdir3 = "game-01"

folder = sprintf("%s/%s/%s/%s/",path,subdir1,subdir2,subdir3)

[1] "./daily/dpu/game-01/"

files<- list.files(folder) - list.files( ) - 경로 안에있는 값 몽땅 반환

sprintf("%s/%s/data.tsv",folder,files)

[1] "2013-05-01" "2013-05-02"

[3] "2013-05-03" "2013-05-04" 

 

data_path <- sprintf("%s/%s/data.tsv",folder,files) - 각각의 tsv자료들을 모음

read_data <- list() - 리스트형식의 빈 공간 생성

for (i in 1: length(data_path)){

read_temp <- read.table(data_path[i], sep= "\ t ", header = T )

read_data[[i]]<-read_temp

} - 각 tsv자료의 데이터들을 뽑아 read_data에 저장

[[1]] - 리스트형식으로 출력

log_date app_name user_id payment

1 2013-09-26 game-01 69575 162

2 2013-09-26 game-01 696807 571

[[2]]

[[3]]

혹은 read_data를 null로 만든다음 rbind 함수 이용 ribind( ) - 읽은자료 모두 결합

read_data <- NULL

for (i in 1: length(data_path)){

read_temp <- read.table(data_path[i], sep= "\t", header = T )

read_data <- rbind(read_data, read_temp)

}

log_date app_name user_id payment - rbind( ) - 여러데이터를 행별로 한번에 묶어서 저장함

1 2013-05-01 game-01 804005 571

2 2013-05-01 game-01 793537 81

3 2013-05-01 game-01 317717 81

4 2013-05-01 game-01 317717 81

 

read_fun <-function(path,subdir1,subdir2,subdir3){ - 사용자 정의함수로 설정

folder = sprintf("%s/%s/%s/%s/",path,subdir1,subdir2,subdir3)

files<-list.files(folder)

data_path <- sprintf("%s/%s/data.tsv",folder,files)

read.table(data_path[1], sep= "t", header = T )

read_data <- NULL

for (i in 1: length(data_path)){

read_temp <- read.table(data_path[i], sep= "\t", header = T )

read_data <- rbind(read_data, read_tem)

}

return(read_data)

}

dpu_data <- read_fun(".","daily","dpu","game-01")

read_fun <-function(path,subdir1,subdir2,subdir3){ - 사용자 정의함수로 설정

folder = sprintf("%s/%s/%s/%s/",path,subdir1,subdir2,subdir3)

files<-list.files(folder)

data_path <- sprintf("%s/%s/data.tsv",folder,files)

read.table(data_path[1], sep= "\t", header = T )

read_data <- NULL

for (i in 1: length(data_path)){

read_temp <- read.table(data_path[i], sep= "\t", header = T )

read_data <- rbind(read_data, read_tem)

}

return(read_data)

}

read_fun <-function(path,subdir1,subdir2,subdir3){ - 사용자 정의함수로 설정

folder = sprintf("%s/%s/%s/%s/",path,subdir1,subdir2,subdir3)

files<-list.files(folder)

data_path <- sprintf("%s/%s/data.tsv",folder,files)

read.table(data_path[1], sep= "\t", header = T )

read_data <- NULL

for (i in 1: length(data_path)){

read_temp <- read.table(data_path[i], sep= "\t", header = T )

read_data <- rbind(read_data, read_temp)

}

return(read_data)

}

dpu_data<- read_fun(".","daily","dpu","game-01")

dau_data <- read_fun(".","daily","dau","game-01") - 다른 경로를 집어넣어도 작동

----------------------10 데이터 처리를 위한 패키지

dplyr 패키지

1. filter()

2. select()

3. mutate()

4. summarise()

5. arrange()

6. group by()

제공해주는 함수 이외에 ”Pipe operator”는 프로그래밍을 조금 더 쉽고 가독성있게 만들어줌.

 

Pipe operator(% > %) - 여러가지 함수의 적용을 연속해서 할 수 있도록 연결해주는 기능을 함.

일반적으로 어떤 값을 계산하기 위해 2개 이상의 함수를 적용해야 할 때, 함수를 중첩해서 사용하거나 변수에 반환 값을 할당한 후 함수를 적용함. – 새로운 변수에 할당필요 <-

예) 양수와 음수가 섞여있는 벡터 절대값 후 평균을 낸다면 일반적으로 다음과 같이 프로그래밍함.

x<- c(1, -1, 2, -2, 3, -3)

mean(abs(x)) - abs 절댓값

x %>% abs() %>% mean()

x %>% abs %>% mean - 소괄호 안해도 됨

 

인자를 넣고 싶으면 . 사용 . - 전에서 입력된 값이 합수 어디에 입력되는지 표시 (혹시나 두번째 인자에 사용되었을 경우 점으로 표시)

x %>% abs( , . ) %>% mean( , , , na.rm= . )

 

filter() 함수 조건에 해당하는 행을 선택할 때 사용되는 함수. Filter( 조건 )

인덱싱(subsetting, 슬라이싱)에서 특정 조건의 행을 선택하는 것과 동일함

head(iris[iris$Sepal.Length>5.5&iris$Petal.Length<6,], n=10)

iris %>% filter(Sepal.Length>5.5 & Petal.Length <6)%>%head(.,n=10) - 위에서부터 10뽑음

 

select() 함수 - 데이터에서 을 이름(문자)이나 위치(정수)로 선택 / 보통 데이터프레임 이용

데이터 프레임, 행렬에서 열을 선택하는 인덱싱과 동일하지만 특정 열을 제외하고 선택할 때 유용함

특히 데이터 프레임에서는 변수 이름으로 negative indexing이 불가능 하지만 select() 함수는 가능함.

iris %>% select(Sepal.Length, Petal.Length) - 셋다 같은 기능

iris %>% select(c(Sepal.Length, Petal.Length))

iris %>% select(c("Sepal.Length", "Petal.Length"))

 

변수 이름으로 negative indexing

iris[ , -c("Sepal.Length", "Petal.Length")] - 원래 데이터프레임 인덱싱에서는 불가능

iris [ ,!(colnames(iris) %in% c("Sepal.Length", "Sepal.Width"))]

iris[ ,-which(colnames(iris) %in% c("Sepal.Length", "Sepal.Width"))] - 원래 이런식으로 인덱싱

 

iris%>%select(-c("Sepal.Length", "Petal.Length")) - 넷다 같은 기능

iris%>%select(-"Sepal.Length", -"Petal.Length")

iris%>%select(-Sepal.Length, -Petal.Length)

iris%>%select(-c(Sepal.Length, Petal.Length))

 

R에서 기본으로 내장된 함수인 subset() 함수 filter()와 select() 함수를 결합해놓은 형태.

하지만 일반적으로 큰 데이터에서는 filter()와 select()을 사용하는 것이 더 빠름.

subset(iris,

subset = Sepal.Length>5.5 & Petal.Length<6, - subset에 만족하는 데이터에서 뽑음

select = c(Sepal.Width, Petal.Width, Species)) - 행 번호 바뀌지 않음(몇번째 행 뽑힌지 그대로 반영)

 

iris%>% - 같은 값 추출

filter(Sepal.Length>5.5 & Petal.Length<6)%>% - 행 번호 바뀜(1~차례대로 )

select(Sepal.Width, Petal.Width, Species)

 

Pipe operator는 코드를 한꺼번에 실행하는 것이 아닌 순차적으로 실행 - 순서를 잘 지켜야함.

iris%>%

select(Sepal.Width, Petal.Width, Species)%>% - 먼저뽑은 변수들이 filter에 없으므로 에러발생

filter(Sepal.Length>5.5 & Petal.Length<6)

 

mutate() 함수

기존 데이터에 새로운 변수(열)을 추가할 때 사용됨.

데이터 프레임에 새로운 열을 추가하는 기능과 동일함. - $ / [ , ] 이용

함수의 인자에 새로운 이름의 변수를 쓰고 새로 입력할 값을 입력하면 됨.

R에서 기본적으로 제공해주는 transform() 함수와 동일하지만 더 개선된 기능을 제공.

iris%>% transform(length_sum = sum(Sepal.Length+Petal.Length)) –모든행 더한값이 새로운변수에 저장

148 virginica 1440.2

149 virginica 1440.2

150 virginica 1440.2

iris%>% transform(length_sum = Sepal.Length+Petal.Length) – 행별로 더한값이 새로운변수에 저장

148 virginica 11.7

149 virginica 11.6

150 virginica 11.0

 

Iris<- iris%>%mutate(length_sum = Sepal.Length+Petal.Length) - Iris2 할당 필요

iris$length_sum= iris$Sepal.Length + iris$Petal.Length - iris데이터에 새로운 변수를 바로 추가

 

transform() 함수보다 mutate() 함수에서 더 개선된 점은 새로 만드는 변수를 참조하여 추가적인 새로운 변수를 만들 수 있는 것.

iris2<- iris%>%

mutate(length_sum = Sepal.Length+Petal.Length,

log_length = log(length_sum)) - 새로만든 변수로 또다른 변수 만들수 있음(연달아서)

 

iris2<- iris%>% - transform 따로따로 진행

transform(length_sum = Sepal.Length+Petal.Length)

iris3<- iris2%>%

transform(log_length = log(length_sum))

 

summarise() 함수

mean, sum 함수 등을 적용하여 요약된 변수 값 생성할 때 사용됨.

주로 group by()와 함께 쓰임. group by()를 사용하지 않으면 일반적인 함수(mean, sum 등)를 적용한 것과 동일함.

iris %>%

summarise(iris_mean = mean(Sepal.Length + Petal.Length))

- group by()와 함께사용하지 않을경우 그냥 mean한 값과 동일한 값 출력

mean(iris$Sepal.Length + iris$Petal.Length)

iris_mean

1 9.601333

arrange() 함수 - 데이터를 특정 변수 기준으로 정렬할 때 사용됨.

인자에 입력되는 변수를 기준으로 기본적으로 오름차순으로 정렬되며 두개 이상의 변수로도 정렬됨.

두개 이상의 변수로 정렬할 때는 가장 먼저 오는 변수의 우선순위가 가장 높고 그다음 순

-order( )함수와 유사

내림차순으로 정렬하고 싶을 때에는 desc() 함수를 변수에 적용하면 됨.

iris %>% arrange(Sepal.Length) - 오름차순 정렬

iris %>% arrange(Sepal.Length, Sepal.Width) - 두개이상변수 정렬

iris %>% arrange(Sepal.Length, desc(Sepal.Width)) - 뒤 변수는 내림차순 정렬

iris %>% arrange(desc(Sepal.Length))

참고) order() 함수 사용

iris[order(iris$Sepal.Length,

iris$Sepal.Width,

decreasing=c(FALSE ,TRUE)), ] - 처음껀 오름차순 / 두번째껀 내림차순 정렬

 

group by() 함수 - 많이 사용

특정 그룹별로 데이터를 처리하기 위한 함수.

group by() 함수는 mutate(), summarise(), arrange() 함수 등과 함께 사용됨.

이전에 배운 by() 함수와 비슷한 기능을 함.

iris%>% - 종별로 새로운 변수를 만듬

group_by(Species)%>%

mutate(iris_length = mean(Sepal.Length + Petal.Length))%>%

as.data.frame -tible 형식이므로 데이터프레임형식으로 바꿔줌

 

iris%>% - 종별로 평균값을 요약

group_by(Species)%>%

summarise(length1 = mean(Sepal.Length),

length2 = mean(Petal.Length))%>%

as.data.frame

 

reshape2 패키지

dplyr 패키지와 더불어 데이터 처리에 가장 많이 쓰이는 패키지.

데이터 구조를 변형하는데 자주 쓰임. cast() 함수와 melt() 함수를 제공함.

melt() 함수 - 열을 없앰

id, 측정 변수, 측정치 형태로 데이터를 재구성하는 함수.

id를 기준으로 측정 변수별 측정값의 형태를 가짐.

melt(데이터, id.vars = “기준변수”, measure.vars = 분류할 변수) - 변수쓸떄 문자형, 숫자형 가능

a<-melt(iris, id.vars = "Species", measure.vars = 1:4)

Species variable value - Species기준으로 나머지 변수들 표현 / 3열(기준변수, 분류할변수, 변수값)

1 setosa Sepal.Length 5.1

2 setosa Sepal.Length 4.9

3 setosa Sepal.Length 4.7

- 원래 iris 데이터는 150행이므로 melt적용시 150X4(나머지 변수개수) = 600행

- id.vars 기준으로 나머지 변수(measure.vars)는 variable로, 그 값은 value로 이동

- 원래는 컬럼별로(변수별로) 따로 뽑아 평균내지만 melt를 이용하면 group_by함수를 통해 변수따라 한번에 평균낼 수 있음

 

mean(iris$Sepal.Length)  변수 칼럼별로 뽑아서 따로따로 평균내야했음

mean(iris$Petal.Length)

 

a%>% - 변수별로 한번에 평균냄

group_by(variable)%>%

summarise(mean_var = mean(value)) %>%

as.data.frame()

 

variable mean_var

1 Sepal.Length 5.843333

2 Sepal.Width 3.057333

3 Petal.Length 3.758000

4 Petal.Width 1.199333

 

a%>%

group_by(variable, Species)%>%

summarise(mean_var = mean(value))%>%

as.data.frame()

 

variable Species mean_var - 변수별, 종별로 따로 계산도 가능

1 Sepal.Length setosa 5.006

2 Sepal.Length versicolor 5.936

3 Sepal.Length virginica 6.588

 

cast() 함수 – 열을 생성

dcast()- 반환값 데이터 프레임 / acast()- 반환값 행렬, 벡터 (데이터처리시 행렬형태 다룰일 거의 없음)

- data : cast()에 적용할 데이터.

- formula : 캐스팅 포뮬러

- fun.aggregate : 데이터의 구조 변환시 여러 값이 한 셀에 모일 경우 적용할 함수.

포뮬러

모형식: ”변수1  변수2 + 변수3 + · · · ” (타겟변수~설명변수)

cast() 함수: ”변수1 1 + 변수1 2 + · · ·  변수2 1 + 변수2 2 + · · · ∼ ...”

cast() 함수: id변수(식별자, 바뀌지않는) ~ 열로 생성할 변수

cast() 함수는 식별자로 지정된 변수의 고유한 값(그룹)에 따라 계산되므로 group by() 와 비슷하지만 그룹별 결과가 열로 추가된다는 차이점이 있음.

dcast(a, formula = Species ~ variable,

fun.aggregate = mean ) - 한셀에 50개 값 표현하기 위해 평균내어 한 값으로 표현

Species Sepal.Length Sepal.Width Petal.Length Petal.Width

1 setosa 5.006 3.428 1.462 0.246

2 versicolor 5.936 2.770 4.260 1.326

3 virginica 6.588 2.974 5.552 2.026

 

a%>% - group_by() 로 정렬시

group_by(Species, variable)%>%

summarise(mean = mean(value))%>%

as.data.frame

Species variable mean

1 setosa Sepal.Length 5.006

2 setosa Sepal.Width 3.428

3 setosa Petal.Length 1.462

4 setosa Petal.Width 0.246

5 versicolor Sepal.Length 5.936

6 versicolor Sepal.Width 2.770

7 versicolor Petal.Length 4.260

8 versicolor Petal.Width 1.326

9 virginica Sepal.Length 6.588

10 virginica Sepal.Width 2.974

11 virginica Petal.Length 5.552

12 virginica Petal.Width 2.026

-------11 데이터 처리를 위한 패키지 (응용) – 여러데이터 결합, 실제데이터에 적용

merge() 함수

두개의 데이터를 특정한 키(key)(변수)를 통해 결합하는 함수.

두개의 데이터를 결합하는 방법: inner join, left join, right join, outer(full) join

merge() 함수는 R에서 기본 내장 함수이고 dplyr 패키지에서도 merge() 함수와 같은 기능을 하는 함수들을 지원함.

Inner_ join

inner_join은 두 개 데이터의 키에서 공통으로 존재하는 데이터만 결합을 시킴.

dat1 = data.frame (name = c("Park", "Moon",

"Hong", "Choi"),

gender = c("M", "F", "M", "F"))

dat2 = data.frame ( name = c("Park", "Moon",

"Hong", "Kim") ,

weights = c(70, 55, 65, 80))

merge(dat1, dat2, by="name", all= F) - 처음 입력하는 인자가 왼쪽, 그다음이 오른쪽 위치 / by= 결합할 기준(키) 변수지정(공통된 변수) (“name”) / all=F (기본값)- 생략가능

name gender weights

1 Hong M 65

2 Moon F 55

3 Park M 70

만약, 키로 사용되는 변수의 값이 고유(unique) 하지 않다면(중복된다면) 고유하지 않은 값들의 모든 조합으로 두 데이터가 결합됨.

dat3 = data.frame ( name = c(" Park ", " Moon ", " Hong ",

" Choi ", " Park ") ,

gender = c("M", "F", "M",

"F", "M"))

dat4 = data.frame ( name = c(" Park ", " Moon ", " Hong ",

"Kim", " Park ") ,

weights = c(70, 55, 65,

80, 62))

merge(dat3, dat4, by= "name", all=F)

name gender weights

1 Hong M 65

2 Moon F 55

3 Park M 70 - 중복된 조합별로 합쳐짐

4 Park M 62

5 Park M 70

6 Park M 62

dplyr 패키지에서 merge(..., all = FALSE) 함수와 동일한 기능을 하는함수인 inner_join() 함수가 존재.

일반적으로 merge() 함수보다 dplyr 패키지에서 제공해주는 함수가 더 빠름

inner_join(dat3, dat4, by= "name", all=F)

left join

함수 인자 중 왼쪽(첫번째 혹은 x)에 입력되는 데이터의 키는 유지한채로 오른쪽(두번째 혹은 y) 데이터의 키에서 왼쪽 데이터의 키에 매칭되는 데이터만 결합

merge() 함수의 all.x 인자에 TRUE를 입력하면 left join이 됨 (기본값은 FALSE)

merge(dat1, dat2, by="name", all.x= T)

name gender weights

1 Choi F NA – dat1의 (park, moon, hong, choi)유지 / choi는 dat2에 없지만 유지시킴

2 Hong M 65

3 Moon F 55

4 Park M 70

dplyr 패키지에서 merge(..., all.x = TRUE) 함수와 동일한 기능을 하는 함수는 left_join() 함수

left_join(dat1, dat2, by= "name")

right join – left join에서 위치만 바뀐 것

함수 인자 중 오른쪽(두번째 혹은 y)에 입력되는 데이터의 키는 유지한채로 왼쪽(첫번째 혹은 x) 데이터의 키에서 오른쪽 데이터의 키에 매칭되는 데이터만 결합함

merge() 함수의 all.y 인자에 TRUE를 입력하면 right join이 됨 (기본값은 FALSE).

merge(dat1, dat2, by="name", all.y= T)

name gender weights

1 Hong M 65

2 Kim <NA> 80 - <NA> - 캐릭터형의 결측치

3 Moon F 55

4 Park M 70

dplyr 패키지에서 merge(..., all.y = TRUE) 함수와 동일한 기능을 하는 함수는 right_join() 함수

right_join(dat1, dat2, by="name")

 

full_join - left, right join 합친 형태

왼쪽과 오른쪽 데이터의 키를 모두 유지한채로 결합함

merge() 함수의 all 인자에 TRUE를 입력하면 됨.

dplyr 패키지의 full_join() 함수

merge(dat1, dat2, by="name", all=T)

name gender weights

1 Choi F NA

2 Hong M 65

3 Kim <NA> 80

4 Moon F 55

5 Park M 70

full_join(dat1, dat2, by="name")

 

실습

- 목적: 어떤 게시물이 좋아요, 공유, 댓글 수가 높을까?

fb_data1<-read.csv("facebook1.csv", header = T)

fb_data2<-read.csv("facebook2.csv", header = T)

colnames(fb_data1) %>% tolower() - 칼럼 이름을 모두 소문자로 바꿔줌

colnames(fb_data1) <- colnames(fb_data1) %>%

tolower() %>% - 칼럼 이름을 모두 소문자로 바꿔줌

gsub(pattern = "[.]", replacement = "_", x = .) .을 _로 바꿔줌 (자세하게 할 경우 정규표현식알아야함)

colnames(fb_data2)<- colnames(fb_data2) %>%

tolower() %>%

gsub(pattern = "[.]",replacement = "_",x = .)

Post.date, Post.hour, Post.minute을 하나의 키로 결합

fb_data<- fb_data1%>%

inner_join(fb_data2, by = c("post_date", "post_hour", "post_minute"))

 

게시물의 댓글, 좋아요, 공유 수는 계절(월)과 요일에 영향을 받을 것으로 생각되어 데이터의 날짜로부터 월과 요일을 추출하여 새로운 변수를 생성.

 

as.Date("20210511", format = "%Y%m%d") – 날짜 형식으로 변환 / %Y - 4자리로 연도표시 2021-05-11

as.Date("210511", format = "%y%m%d") - %y - 2자리로 연도표시 바꿀데이터, 포맷= 파뀔형식

as.Date("2021/05/11", format = "%Y/%m/%d")

as.Date("2021.05.11", format = "%Y.%m.%d")

날짜표기 형식에 따라 다른 format으로 표현

 

class(fb_data$Post.date) [1] "integer" – 정수형식이므로 캐릭터형식으로 바꿔줌

fb_data$post_date<-fb_data$post_date%>%as.character%>%

as.Date(., format = "%Y%m%d")

 

str(fb_data)

$ post_date : Date, format: "2016-12-29" ... – class가 Date로 바뀜(Date class에 맞는 여러 함수적용가능)

 

fb_data$month <- fb_data$post_date%>% months() – 월추출

fb_data$weekday <- fb_data$post_date%>% weekdays() – 요일추출

 

목적: 전체(페이지) 좋아요 수에 따라 댓글, 좋아요, 공유 수가 변하는지 알아보기

- 페이지 좋아요 수가 크면 많은 사람들이 찾는 페이지이므로

-  3개의 범주를 생성 – 좋아요 수 상위0~33%, 33~66%, 66~100% 설정

절단값 사이 값을 그룹으로 묶어줌

qt<- quantile(fb_data$page_total_likes, - 설정한 분위수에 해당하는 값 반환

probs =c(0,1/3,2/3,1) )

 

cut(fb_data$page_total_likes, - 절단값 사이 값을 그룹으로 묶어줌

breaks = qt) - (8.14e+04,1.19e+05] – 초과, 이하로 묶어주기 때문에 0% 값은 포함되지 않음

 

cut(fb_data$page_total_likes,

breaks = qt, right = F) - [8.14e+04,1.19e+05)  이상, 미만으로 묶어주기 때문에 100%값은 포함되지 않음

 

qt[4] = qt[4] +1 - 100%값을 살짝(1만큼) 키워준 다음 적용  모든 값이 이상, 미만안에 포함됨

group_like<-cut(fb_data$page_total_likes,

breaks = qt, right = F)

levels(group_like) [1] "[8.14e+04,1.19e+05)" "[1.19e+05,1.35e+05)" "[1.35e+05,1.39e+05)"

- 3 그룹으로 나뉜 것 확인

group_like<-cut(fb_data$page_total_likes,

breaks = qt, right = F,

labels = c("low", "medium", "high") - 세그룹 이름 붙여줌

fb_data$levels <- group_like – levels 라는 변수에 넣음

 

결측치(NA)가 존재하는지 확인. / 결측치가 존재한다면 결측치를 처리

<결측치 처리 방법 1> - 결측치 포함된 해당 데이터 전체(행전체)를 삭제후 계산

complete.cases(fb_data) – NA 들어있는 행 F / 없으면 T

fb_data<- fb_data[complete.cases(fb_data),] –NA 없는 데이터만 추출

 

fb_data<-fb_data[complete.cases(fb_data[ , c("comment", "like", "share")]), ]

-"comment", "like", "share" 세 변수의 NA값만 확인하여 추출

 

fb %>% select("Comment", "Like", "Share") %>% complete.cases() %>% fb[.,]

<결측치 처리 방법 2> - 결측치가 0을 나타내거나, 0으로 처리해도 문제없을시 0입력

 

fb_data[ ,c("comment", "like", "share")][is.na(fb_data[ ,c("comment", "like", "share")])] <-0

[1] NA NA NA NA NA

- NA에 해당하는 데이터를 추출한 후 0입력

 

<결측치 처리 방법 3> - 결측치를 평균으로 대체

- 좋아요 수 평균으로 대체

- 원래데이터에 그룹평균된 컬럼 추가 – 행별로 보다가 결측치 있을 경우 끼움

impute_dat<-fb_data %>%

group_by(levels)%>% - levels별로 그룹 만들어줌

mutate(mean_likes = mean(like, na.rm=T), - 각 levels 별로 평균구함

mean_share = mean(share, na.rm=T),

mean_comment = mean(comment, na.rm=T))%>%

ungroup()%>% - 지정한 그룹 해제

select(mean_likes, mean_share, mean_comment) - 지정한 변수들만 뽑아줌

 

mean_likes mean_share mean_comment

<dbl> <dbl> <dbl>

1 171. 25.8 7.04

2 171. 25.8 7.04

3 171. 25.8 7.04

 

fb_data$like[is.na(fb_data$like)] <- impute_dat$mean_likes[is.na(fb_data$like)]

NA <- [1] 171.071 (NA가 있는 그룹평균의 값 추출)

fb_data$comment[is.na(fb_data$comment)] <- impute_dat$mean_comment[is.na(fb_data$comment)]

fb_data$share[is.na(fb_data$share)] <- impute_dat$mean_share[is.na(fb_data$share)]

 

이러한 방법 이외에도 모델을 통해 결측값을 처리하는 등 다양한 방법이 존재하지만 이번 강의 수준을 넘으므로 생략 (참고 – 결측치 처리방법: imputation)

여전히 결측값이 존재하는 행은 제거함 – 댓글, 좋아요, 공유 변수 외에 다른 곳 결측치 있는경우

fb_data<- fb_data[complete.cases(fb_data), ]

 

여전히 결측치 있는지 확인

summary(fb_data) - 결측치 있는경우 NA's로 표현됨

sum(is.na(fb_data)) - is.na 함수는 NA값을 T(1)로 반환하므로 T가 없는 경우 더하면 0이 나옴

 

페이스북에 게시물 종류에 따라서 댓글, 좋아요, 공유 수가 다른지 확인하기 위해 게시물 종류별 평균을 계산

mean_by_type<- fb_data%>%

group_by(type)%>%

summarise(mean_comment = mean(comment), mean_share = mean(share), mean_like = mean(like))

 

as.data.frame(mean_by_type)

type mean_comment mean_share mean_like

1 Link 2.818182 12.90909 73.31818

2 Photo 7.510588 27.14429 182.80017

3 Status 8.911111 31.42222 176.71111

4 Video 12.285714 52.14286 231.42857

 

월, 요일별로도 댓글 등의 수가 달라지는지 확인

그룹만 변하고 평균을 계산하는 코드를 반복적으로 사용하기 때문에 함수로 정의.

가변길이인자로 처리 – 캐릭터형이 아닌 변수로 입력해도 그대로 넘어감

grouped_mean = function(data, ...){

res <- data%>%

group_by(...)%>%

summarise(mean_comment = mean(comment),

mean_share = mean(share),

mean_like = mean(like))

return(res)

}

as.data.frame(grouped_mean(fb_data, weekday))

weekday mean_comment mean_share mean_like

1 금요일 6.089552 27.46017 172.1493

2 목요일 10.352113 31.61972 220.5493

3 수요일 13.593750 37.53125 236.6406

4 월요일 7.926471 24.76471 204.3382

5 일요일 4.012195 21.42272 128.7805 - 주말에는 놀기바빠 이용량 줄어듬

6 토요일 5.296296 23.56582 136.3712

7 화요일 6.530303 26.71212 167.2121

 

as.data.frame(grouped_mean(fb_data,month))

month mean_comment mean_share mean_like

1 10월 6.033333 24.17490 156.83452

2 11월 6.111111 25.15556 154.48889

3 12월 6.260000 22.90000 172.18000

4 1월 6.208333 31.91667 124.20833

 

비용 지불 여부에 따라 게시물 종류의 좋아요 값이 어떻게 변하는가?

(두개 변수의 그룹별 댓글, 좋아요, 공유 수의 평균 구함)

보기 편하도록 dcast함수 이용 – 행: 게시물 종류/ 열: 비용 지불 여부 / 각 셀은 좋아요의 평균

(그냥 group_by() 사용할 시 밑으로 길게 데이터 표현됨- 보기 불편함)

 

어떤 변수로 셀에 넣을 값을 계산할 것인가

fb_data %>% dcast(. , formula = type ~ paid, - 타겟변수(행: type) / 설명변수(열: paid)

value.var = "like", - 어떤 변수로 셀에 넣을 값을 계산할 것인가

fun.aggregate = mean)

type 0 1

1 Link 79.5625 56.66667

2 Photo 160.2127 240.88235

3 Status 147.8286 277.80000

4 Video 216.0000 243.00000

 

a<- fb_data %>% group_by(type, paid) %>%

summarise(mean_like = mean(like))

type paid mean_like - group_by() 사용시 보기 불편함

1 Link 0 79.56250

2 Link 1 56.66667

3 Photo 0 160.21265

4 Photo 1 240.88235

5 Status 0 147.82857

6 Status 1 277.80000

7 Video 0 216.00000

8 Video 1 243.00000

 

세개 변수별 좋아요 평균

fb_data %>% dcast(. , formula = type + levels ~ paid,

value.var = "like",

fun.aggregate = mean)

type levels 0 1

1 Link low 92.2000 21.5000

2 Link high 58.5000 74.2500

3 Photo low 156.6990 201.5854

4 Photo medium 177.0096 270.0667

---------------------12 R 통계 I

대표값 - 주어진 자료를 대표하는 특정 값 - 평균, 중앙값, 최빈값, 분산 등

평균 - 데이터의 중심 경향을 나타내는 척도 / 정확하게는 모평균과 표본평균을 구분해야하지만 이후부터는 비전공자도 잘 알고있는 표본평균을 평균이라 지칭.

산술평균 - 일반적으로 알고 있는 평균 / 데이터를 모두 합하여 그개수로 나눈 값. mean()

기하평균 - 물가상승률이나 인구증가률등 기존 값에 곱으로 구해지는 값에 사용됨.

사용자 정의함수 or psych 패키지의 geometric.mean() 함수를 통해 계산

y<-100

y*1.01*1.02*1.03 [1] 106.1106 3년간 물가상승률

x1<-mean(c(1.01, 1.02, 1.03))

y*x1^3 [1] 106.1208 - 산술평균으로 물가상승률의 평균계산

x2<-prod(c(1.01, 1.02, 1.03))^(1/3) - prod( ) 안의 값 모두 곱함 ^(1/3) – 개수만큼 제곱근값을 씌움

y*x2^3 [1] 106.1106 - 기하평균으로 계산시 올바른값

 

geometric.mean <- function(x){ - 사용자정의함수

n <- length(x)

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

}

geometric.mean(c(1.01, 1.02, 1.03))

 

조화평균  평균속도 계산할 때 사용됨 / 사용자 정의함수 or psych 패키지의 harmonic.mean() 함수를 통해 계산

y<-10 - 총 10km 거리 이동

x<- c(1, 5) - 처음 5km는 1km/h 다음 5km는 5km/h의 속도로 이동 (총 6시간 이동)

mean(x) *6 - 산술평균으로 6시간 이동시 18km 이동

x1<- 2 / (1/1 + 1/5)

x1*6 [1] 10 - 조화평균으로 6시간 이동시 10km 이동

 

harmonic.mean <- function(x){ - 사용자정의함수

n <-length(x)

return(n/ sum(1/x)) - 총 개수를 각 값의 역수의 합으로 나눠줌

}

harmonic.mean(x)

 

rnorm( ) – 정규분포에서 임의로(랜덤하게) 값을 추출

rnorm(n = 100, mean = 173, sd = 2) - 뽑을 개수 / 평균 / 표준편차

 

분산 (variance) - 자료의 중심(평균)으로부터 퍼짐성을 나타내는 값 var( )

표준 편차(standard deviation) - 분산에 제곱근을 씌운 것 sqrt(var( )) sd( )

분위수 - 자료를 크기 순서에 따라 나열한 후 q% 값이 그 값보다 작거나 같게 되는 값 / 자료의 상대적 위치, 분포의 치우침을 알 수 있음. quantile()

x<- rnorm(10) - 무작위 10개 추출

quantile(x,c(0.3, 0.7)) - 0.3, 0.7분위 추출

30% 70%

-0.5609950 0.3816941

중앙값 > 평균 - 오른쪽에 자료가 몰려있음

중앙값 < 평균 - 왼쪽에 자료가 몰려있음

 

다섯수치 요약- 자료의 최소값, 제1사분위수, 중앙값, 제3사분위수, 최대값으로 요약된 수치. fivenum( )

(여섯수치요약 + 평균) summary()

 

최빈값(mode) - 자료에서 가장 많이 나타난 값 table() / which.max( )

x<- c(1,1,1,2,2,3,4)

tt<- table(x)

tt[which.max(tt)]

1 -1이 3번 나옴

3

데이터 프레임에서 자료들의 특성을 나타내주는 유용한 함수로 Hmisc 패키지의 summary.formula() 함수가 존재

summary( Sepal.Length ~ Species + Sepal.Width, iris, fun = sd)

- 타겟변수 ~ 설명변수 / fun = 분산,평균, 표준편차 어떤 기준으로 반환할지

Sepal.Length N= 150

+-----------+----------+---+------------+

| | | N|Sepal.Length|

+-----------+----------+---+------------+

| Species| setosa| 50| 5.006000|

| |versicolor| 50| 5.936000|

| | virginica| 50| 6.588000|

+-----------+----------+---+------------+

|Sepal.Width| [2.0,2.9)| 47| 5.929787|

| | [2.9,3.1)| 36| 6.027778|

| | [3.1,3.4)| 30| 5.966667|

| | [3.4,4.4]| 37| 5.454054|

+-----------+----------+---+------------+

| Overall| |150| 5.843333|

+-----------+----------+---+------------+

 

교차표(cross table, contingency table) - 범주형 자료의 도수를 표를 통해 나타낸 것. table() / xtabs()

예) 성별따른 흡연여부 /

usedcar<- read.csv("C:\\Users\\Uos\\Desktop\\data (12)\\usedcars.csv", header = T)

usedcar$cc_group <- ifelse(usedcar$cc > 1900, "H", "L")

t1<- table(usedcar$cc_group, usedcar$automatic) - 행, 열 순서used

0 1

H 7 11 - 각 변수 해당하는 개수 세줌

L 6 6

xtabs(~cc_group + automatic, data = usedcar) - 포뮬러 왼쪽값은 비워둠 ~ 설명변수

automatic

cc_group 0 1

H 7 11

L 6 6

margin.table() – 주변합 / prop.table() – 주변비율

margin.table(t1, margin = 1) - margin = 1 (열을 다 더함)(행방향으로 산출)

H L

18 12

margin.table(t1, margin = 2) - margin = 2 (행을 다 더함)(열방향으로 산출)

0 1

13 17

 

prop.table(t1, margin = 1)

0 1

H 0.3888889 0.6111111 7/18 11/18

L 0.5000000 0.5000000

 

t1/sum(t1) - 전체비율

0 1

H 0.2333333 0.3666667 7/30 11/30

L 0.2000000 0.2000000 6/30

 

변수간 독립성 확인하기 – 변수간 연관성이 있나 (카이스퀘어 검정)

예) 엔진 cc와 변속기어의 수동/자동 여부와 관계가 있는가 (추측 - 엔진cc 높으면 자동기어일 것이다)

교차표에서 전체 중에 cc group의 범주들이 갖는 비율을 계산해보면 ”H”가 0.6 ”L”은 0.4임

rp<-margin.table(t1, margin = 1) / sum(t1)

H L

0.6 0.4

- 다른 변수들을 고려하지 않고 cc group 변수만을 봤을 때의 비율

automatic 변수의 범주들이 갖는 비율을 계산

cp<-margin.table(t1, margin = 2 ) / sum(t1)

0 1

0.4333333 0.5666667

 

cc group 변수와 automatic 변수가 어떤 관계가 없다면 (독립이라면) 전체 30개 중 (”H”, ”0”)의 범주에 들어가는 도수는 30(전체자료) × 0.6 × 0.4333 = 7.8로 기대할 수 있음

기대되는 도수 7.8과 차이가 많이 난다면 cc group 변수와 automatic 변수가 서로 연관이 있어서 특별히 (”H”, ”0”)일 때 기대되는 도수와 차이가 많이 발생한 것이라고 생각할 수 있음

-기대도수(서로 연관없을 경우의 값)와 실제 관측된 값과 비교 – 차이 많이 나면 연관있음(종속)

expected <- 30*outer(rp, cp, FUN = "*") outer- 조합별로 계산 FUN -적용할 함수 (“ * “ 곱하기 적용)

0 1

H 7.8 10.2 30*0.6*0.4333 30*0.6*0.5666

L 5.2 6.8

 

t1 – expected 실제관측값 – 기대도수(연관없을경우, 독립일경우값) / 값이 크면 연관성큼

0 1

H -0.8 0.8 - 엔진높으면서 수동은 기대값보다 적게나옴

L 0.8 -0.8 - 엔진낮으면서 자동은

- 엔진이 높을수록 자동기어가 많구나 / 엔진이 낮을수록 수동기어가 많구나

 

그래프

상자 그림(Box plot) - 다섯 수치 요약을 통해 나타낸 그래프 / 자료분포, 이상치 등 식별 boxplot()

boxplot(iris$Sepal.Width)

 

만약 하나의 그래프에 Species 변수의 그룹별로 상자그림을 그리고 싶다면 포뮬러이용

boxplot ( Sepal.Width ~ Species , iris )

- setosa종이 versicolor종보다 너비가 큼

 

히스토그램 - 자료의 분포 시각적으로 보여줌 hist( )

hist(iris$Sepal.Length,breaks = 50) - breaks 자료 범위 나누는 정도를 지정(큰 수일수록 촘촘)

hist(iris$Sepal.Length,breaks = c(0,4,9,10)) - breaks 정확한 범주를 지정할 수 있음

 

산점도 - 데이터를 점으로 표시 plot() - type인자에 “l”입력시 선그래프 그려짐 / col – 색 지정 / pch-점모양지정(1=점,2=세모,16=꽉찬점…)

iris_temp <- iris %>% arrange(Sepal.Width) - 자료를 오름차순으로 정렬

plot(iris_temp$Sepal.Width, iris_temp$Sepal.Length, type = "l", col="red") – 으로 연결 (X축, Y축 순서)

 

 

막대 그래프 barplot()

mean_iris <- iris %>%

group_by(Species) %>%

summarise_all(mean) - 그룹진 변수 제외한 나머지 변수를 괄호에 적용

Species Sepal.Length Sepal.Width Petal.Length Petal.Width

1 setosa 5.006 3.428 1.462 0.246

2 versicolor 5.936 2.770 4.260 1.326

3 virginica 6.588 2.974 5.552 2.026

 

barplot(mean_iris$Sepal.Length,names.arg = c("setosa", "versicolor","virginica"))

*포뮬러 이용

barplot(Sepal.Length ~ Species, data = mean_iris) – 타겟변수 ~ 설명변수, 들어있는 데이터

 

응용 I

게임 로그 데이터

1) 결제를 하는 유저와 하지 않는 유저의 비율

2) 게임 접속이 많은 유저가 더 결제를 많이 하는지

load("game_log.RData")

head(dau_data) - 로그인 데이터 데이터 대략적인 구조 확인

head(dpu_data) - 결제 데이터

 

str(dau_data) - 데이터 구조확인

str(dpu_data)

정수로된 유저아이디를 캐릭터형태로 변경 (유저아이디 실수로 사칙연산 못하게)

dau_data$user_id = as.character(dau_data$user_id)

dpu_data$user_id = as.character(dpu_data$user_id)

 

유저아이디별로 로그인 횟수 구하기

n_login <- dau_data %>%

group_by(user_id) %>%

summarise(count = n()) - dplyr 패키지 함수/ 개수 세줌

user_id count

<chr> <int>

1 100012 37

2 100019 3

3 100020 15

 

유저아이디별 결제총액 구하기 – 게임접속횟수와 결제액의 관계를 알기위해

t_pay <- dpu_data %>%

group_by(user_id) %>%

summarise(total_payment = sum(payment))

user_id total_payment

<chr> <int>

1 103581 1466

2 104243 162

3 106832 31256

 

두 데이터를 유저아이디로 결합 (유저아이디, 로그인데이터, 결제액)

- 자료크기: n_login > t_pay 로그인하고 결제안한데이터가 n_login에 포함

nt_data <- left_join(n_login, t_pay, by= "user_id")

user_id count total_payment

<chr> <int> <int>

1 100012 37 NA

2 100019 3 NA

3 100020 15 NA

NA- 결제안함 - 0으로 처리

nt_data$total_payment[is.na(nt_data$total_payment)] = 0

 

1) 결제한 유저와 하지 않은 유저의 비율 – payment값 0, 0아닌 데이터 비율

nt_data %>%

summarise(no_pay = sum(total_payment==0)/length(total_payment),

pay = sum(total_payment!=0)/length(total_payment))

no_pay pay

1 0.991 0.00920

 

2) 게임 접속이 많은 유저가 더 결제를 많이 하는지

유저의 접속 빈도를 세개의 범주로 나누기 – 교차표에서 셀마다 범주다르게

결제한 사람들만 가지고 분석진행

pay_dat<- nt_data %>% filter(total_payment >0)

 

산점도로 대략적인 관계확인

plot(pay_dat$count, pay_dat$total_payment)

 

교차표로 확인 - 접속량 범주화 하기 위해

로그인한 횟수 데이터를 분위수를 통해 범주지정

n_log_qt <- quantile(pay_dat$count, probs = c(1/3, 2/3, 1))

33.33333% 66.66667% 100%

22 75 185

 

n_log_qt[length(n_log_qt)] =n_log_qt[length(n_log_qt)] +1 - 100% 속하는 데이터를 이상, 미만 범주에 포함시키기 위해

pay_dat$n_log<- cut(pay_dat$count, breaks = c(0, n_log_qt), right = F,

labels = c("low", "mid", "high"))

33.33333% 66.66667% 100% 0~22 / 22~75 / 75~186 – 세범주

0 22 75 186

 

결제액 데이터를 분위수를 통해 범주지정

n_pay_qt <- quantile(pay_dat$total_payment, probs = c(1/3,2/3,1))

33.33333% 66.66667% 100%

162 1142 119594

 

n_pay_qt[length(n_pay_qt)] = n_pay_qt[length(n_pay_qt)] +1

pay_dat$n_pay <- cut(pay_dat$total_payment, breaks = c(0,n_pay_qt), right = F,

labels = c("low", "mid", "high"))

 

table(pay_dat$n_log, pay_dat$n_pay)

 

기대도수와 비교

tt<-table(pay_dat$n_log, pay_dat$n_pay) - 행, 열 순서

 

a1<- margin.table(tt,1) / sum(tt) – 전체에서 접속 범주별 결제비율

a2<- margin.table(tt,2) / sum(tt) – 전체에서 결제 범주별 접속비율

 

기대도수 구하기

expect_t <- sum(tt) * outer(a1, a2, FUN = "*")

관측된 도수, 기대도수 비교

low mid high - 관측된 도수

low 63 79 22

mid 36 77 58

high 27 53 90

low mid high - 기대 도수 – 독립이다(상관관계없을 경우)

low 40.91881 67.87327 55.20792

mid 42.66535 70.77030 57.56436

high 42.41584 70.35644 57.22772

tt - expect_t (결제)

low mid high

(접속) low 22.0811881 11.1267327 -33.2079208  접속을 적게했는데 결제많이한사람은 드물다

mid -6.6653465 6.2297030 0.4356436

high -15.4158416 -17.3564356 32.7722772

+값은 기대도수(서로 관계 없음)보다 큰 값 = 서로 관계있음 = 많다

-값은 = 서로 관계없음 = 드물다

즉, 접속을 많이할수록 결제도 많이함


----------------------12 시각화----------------------------------

그래프 패키지

ggplot2- 고정된 그래프

plotly- interactive한 그래프 - 클릭시 하이라이트, 모양바뀌는 등

 

ggplot2 패키지

먼저 ggplot() 함수에 데이터를 입력해 ggplot 객체로 만들어주어야 함.

ggplot() 함수에 데이터 입력 = 도화지와 붓, 물감등 그림을 그리기 위해 재료를 준비하는 것

데이터에 맞춰 그릴환경을 세팅하는 것

mapping 인자 - 그래프의 x축, y축으로 사용할 변수를 aes( )를 통해 입력 (도화지를 그림 크기에 맞게 자르고 눈금을 표시).

ggplot(data = iris, mapping = aes(x=Sepal.Length, - x,y축만 그려짐 – 도화지생성

y=Sepal.Width))

 

geom () 함수를 통해 어떤 그림을 그릴 것인지 선택

geom_point 산점도 / geom_line 선그래프 / geom_barplot 막대그래프 / geom_boxplot 상자그래프

ggplot 객체(도화지)에 ”+”를 통해 연속해서 geom () 함수(그릴 그림)와 연결해 그래프를 그림

ggplot(data = iris,

mapping = aes(x=Sepal.Length,

y=Sepal.Width)) + geom_point() + geom_line()

geom () 아무것도 입력하지 않는다면 - 이전 ggplot 함수에서 정의한 데이터를 사용

추가적인 데이터 이용하여 그래프를 그리기 가능 - geom ()함수내 data 인자와 mapping 인자에 추가 데이터를 입력 – 이미 정의한 도화지에 새로운 데이터이용하여 표현가능

ggplot(data = iris, mapping = aes(x = Sepal.Length, y = Sepal.Width))+

geom_point() + geom_point(data = iris, mapping = aes(x = Petal.Length, y = Petal.Width))

 

내장함수인 plot() 함수와 points() 함수를 사용해도 유사하게 그리는 것이 가능

points() - 이미 그려진 그래프 상에 추가적인 점을 찍을 때 / 그려진 그래프상에 점을 찍으므로 x축과 y축 범위를 벗어난 점은 보이지 않음

plot(iris$Sepal.Length, iris$Sepal.Width, pch =16, xlim = c(0,10), ylim = c(0,5)) – 축범위 설정가능

points(iris$Petal.Length, iris$Petal.Width, pch=16)

with(iris ,plot(Sepal.Length, Sepal.Width, pch=16 )) – with() - 데이터 입력후, 각 변수이름만으로 그래프그리기

with(iris ,points(Petal.Length, Petal.Width, pch=16 ))

 

color 또는 fill 인자에 그룹을 나타내는 변수를 지정한다면 그룹별로 그래프의 색을 구분해서 그려줌

color - 선, 점 등의 색 / 막대그래프 등 도형으로 이루어진 그래프를 그릴 때 테두리 색을 결정

fill - 도형의 테두리 안쪽 색

ggplot(data = iris,

mapping = aes(x=Petal.Length,

y=Petal.Width,

color=Species,

shape=Species)) +geom_point() - 종별로 다른 컬러, 모양지정

ggplot(data = iris,

mapping = aes(x=Petal.Length,

y=Petal.Width)) +geom_point(color = "red") – 모든 점 빨간색지정

 

aes() 또는 geom () 함수내 size, alpha, shape 인자

size=점크기 / alpha=색 투명도(0투명 ~ 1불투명) / shape=점모양 (“triangle”삼각형) 번호해당모양있음

aes()  그룹별로 하고싶을 때(색, 모양등) / geom () - 단일값으로 바꾸고싶을 때(전체적으로 다바뀜)

실습

ggplot(data = iris_s,

aes(x=Sepal.Length, y=Sepal.Width,

color = Species , size = Sepal.Width)) + geom_point()

 

 

ggplot(data = iris,

aes(x= Sepal.Length,

y= Sepal.Width)) + geom_point() + facet_grid(~ Species)

- 종별로 다른 그래프에 표시 (~설명변수-나눌변수 포뮬러표시)

 

내장함수 이용하여 유사하게 그림

plot(iris$Petal.Length, iris$Petal.Width, col = iris$Species, pch=16)

with(iris, plot(Petal.Length, Petal.Width, col=Species, pch=16))

 

그래프 설정을 바꿔줌

par(mfrow = c(1,3)) - 그래프를 1행, 3열 형태로 나눠줌

with(iris, plot(Petal.Length, Petal.Width, col=Species, pch=16))

-한번실행할 때마다 왼쪽부터 차례로 하나씩 그려짐 (총 3번 실행시킴)

 

iris_group <- by(iris, INDICES = iris$Species, FUN = function(x){return(x)}) – 사용자정의함수로 넣은 값 그대로 출력 - 종별로 그룹나뉘어서 출력됨

iris %>% filter(Species == "setosa") - 종별로 여러번 적용한 것과 같은 값

par(mfrow = c(1,3))

for(i in 1:length(iris_group)){

with(iris_group[[i]],

plot(Petal.Length, Petal.Width,

col = i, pch=16, xlim=c(0,8), ylim=c(0,5)))

}

 

ggplot에서 xlab() - x축 이름 / ylab() -축 이름 / ggtitle() - 그래프 전체 타이틀

ggplot(data = iris,

aes(x= Sepal.Length,

y= Sepal.Width,

color = Species)) + geom_point() +

xlab("Length") + ylab("Width") + ggtitle("IRIS")

aes()의 color 또는 fill 인자에 값 혹은 변수를 할당하면 자동으로 범례(legend)를 생성

범례수정 - 이산형 변수 scale_color(fill,shape …)_discrete() / scale_color(fill,shape …)_manual()

- 연속형 변수 scale_color_continuous() / scale_color_gradient()

ggplot(data = iris,

aes(x= Sepal.Length,

y= Sepal.Width,

color = Species)) + geom_point() + - Species 이산형변수

scale_color_discrete(name = "A",

labels = c("a", "b", "c"))

 

ggplot(data = iris,

aes(x= Sepal.Length,

y= Sepal.Width,

color = Species)) + geom_point() +

scale_color_manual(name = "A",

labels = c("a", "b", "c"),

values = c("green", "blue", "red")) - #FF6C90 색 기호로도 표현 가능

- 각 범례 색도 지정가능(values)

 

ggplot(data = iris,

aes(x= Sepal.Length,

y= Sepal.Width,

color = Sepal.Width)) + geom_point() + - Sepal.Width 연속형변수

scale_color_continuous(name = "A")

 

ggplot(data = iris,

aes(x= Sepal.Length,

y= Sepal.Width,

color = Sepal.Width)) + geom_point() +

scale_color_gradient(name = "A",

low = "blue",

high = "red",

breaks = c(3,4))

 

geom line() – 선그래프 / economics데이터로 날짜별로 변수의 변함보임

ggplot(data = economics, aes(x=date, y= unemploy))+

geom_line(size = 2, color = "red", alpha = 0.5) alpha -투명도

 

economics 데이터에서 열마다 그래프를 그릴 때 – 변수 일일이 다 써서 그릴수 있음

ggplot(data = economics, aes(x=date, y= unemploy))+

geom_line(size = 2, color = "red", alpha = 0.5)+

geom_line(data = economics, aes(x=date, y= pce))+

geom_line(data = economics, aes(x=date, y= pop))+

geom_line(data = economics, aes(x=date, y= psavert))

 

또는 library(reshape2) 패키지 이용하여 그룹나타내는 변수와 값들로 표현

economics_l <- melt(economics, id.vars = "date", measure.vars = 2:6)

date variable value

1 1967-07-01 pce 506.7

2 1967-08-01 pce 509.8

3 1967-09-01 pce 515.6

ggplot(economics_l, aes(x = date, y = value, color = variable))+

geom_line(size = 2) +

scale_color_discrete(name = "Type")

 

내장함수로도 그릴수 있음

 

geom bar()- 막대그래프 / diamonds데이터로 전체데이터에서 각 품질의 개수확인

ggplot(diamonds, aes(x=cut))+ - y값은 개수가 기본값

geom_bar() - 그래프 높이가 개수가 됨

 

입력하는 데이터의 값으로 막대의 높이를 설정 stat = "identity

mean_carat <- diamonds %>%

group_by(cut) %>%

summarise(mean_carat = mean(carat))

ggplot(mean_carat, aes(x=cut, y = mean_carat, fill = cut))+

geom_bar(stat = "identity") - y축은 개수가 아닌 품질별 carat의 평균

 

iris데이터로 실습

iris_s <- iris %>%

group_by(Species) %>%

summarise_all(mean)

iris_m <- iris_s %>% melt(., id.vars = "Species", measure.vars = 2:5)

ggplot(iris_m, aes(x = Species, y= value, fill = variable)) +

geom_bar(stat = "identity", position = "dodge") – 옆으로 세움

안할 경우 위로 쌓음

geom histogram() - 히스토그램

ggplot(iris, aes(Sepal.Width, fill = Species)) + - x,y 변수 없음 데이터만입력

geom_histogram(position = "dodge")

position = "identity", alpha=0.3 - 겹치고 투명도 조절가능

 

geom boxplot() - 상자 그래프

ggplot(iris, aes(x=Sepal.Width, fill = Species)) +

geom_boxplot()

ggplot(iris, aes(y=Sepal.Width, fill = Species)) +

geom_boxplot() x,y 에 따라 가로세로가 바뀜

728x90

'R' 카테고리의 다른 글

R 기본문법 정리 - 1  (2) 2023.09.03