Hard skills/R (46)

우분투에 R과 Rstudio Server 설치



1. R 설치

sudo apt-get install r-base



2. R studio 설치


아래 링크에서 보고 따라하면 됨

https://www.rstudio.com/products/rstudio/download-server/


이건 1.1.383 version 기준


sudo apt-get install gdebi-core

wget https://download2.rstudio.org/rstudio-server-1.1.383-amd64.deb

sudo gdebi rstudio-server-1.1.383-amd64.deb



3. 웹브라우저 접속

http://<server-ip>:8787


위 처럼 접속해서 운영체제 아이디/패스워드를 통해 로그인

R 언어의 중요한 기초 개념 정리 


Vectorization


d <- 1:5

d.r <- c(2,1,4,5,3)

d-d.r # -1 1 -1 -1 2 (element-wise operation)

d-mean(d) # -2 -1 0 1 2 (평균인 3이 5개인 vector를 알아서 만들어서 element-wise operation을 수행한다.)


x <- c(2,3,5,7,11)

var(x) # 12.8


* 분산을 구하는 코드를 작성할 때, 일반적인 프로그래밍이라면 벡터안에 있는 원소의 수 만큼 for문을 돌면서 평균을 구하고 분산을 구한다. 하지만 R의 경우 일반적인 프로그래밍처럼 구하지 않는다. 우선, R에서 for문을 사용하는것은 좋지 않다. R은 C로 구현되었는데 for문으로 계속 연산을 실행하면 이 연산 실행하는 수만큼 C 컴파일러와 정보를 주고받는다.


xbar = mean(x)

numer = sum((x-xbar)^2)

n=length(x)

variance = numer/(n-1)


따라서 위와같이 벡터단위로 함수를 실행하여 구하는 게 일반적이고, 효율적인 방법이다.


HELP


객체의 정보를 알아보기 위해 help 함수를 활용하자.


help("mean")

help.search("mean")

apropos("mean") # mean이 포함된 함수를 모두 출력



데이터 구조와 접근법 개요


Series

1:10 # 1 2 3 ... 10


Arithmetic Series

seq(1,9,by=2) # 1,3,5,7,9

seq(1,9,length=5) # 1,3,5,7,9 (1,9를 처음과 끝으로 하여 5개의 수를 만든다.)


Repeated Vector

rep(1,10) # 1 1 1 1 1.... 1

rep(1:3, 3) # 1 2 3 1 2 3 1 2 3

rep(1:3, each=3) # 1 1 1 2 2 2 3 3 3


Assessing data with index (만든 데이터의 원소를 어떻게 불러오나)

d <- 1:5

d[2] # 2

d[1:3] # 1 2 3

d[c(1,3,5)] # 1 3 5


Negaive Index

d[-1] # 2 3 4 5

d[-c(4:5)] # 1 2 3


Replace data

d[1] <- 10

d # 10 2 3 4 5


d[1:3] <- c(10,20,30)

d # 10 20 30 4 5


Get data from logical value

d <- c(1,2,3,4,5)

d > 3.5 # FALSE FALSE FALSE TRUE TRUE

which(d>3.5) # 4 5

d[c>3.5] # 4 5 (TRUE인 원소만 값을 불러온다.)


NA


a <- c(0,1,0,NA,0,0)

a > 0 # FALSE TRUE FALSE NA FALSE FALSE (NA는 어떤 수학적인 연산을 할 수 없다.)

is.na(a) # FALSE FALSE FALSE TRUE FALSE FALSE

mean(a) # NA

mean(a, na.rm=TRUE) # 0.2



Data Type


vector, matrix, array, data.frame, list 5개가 있다.


* matrix와 vector는 비슷하다.


x <- 1:10

attr(x, 'dim') <- c(2,5)

attributes(x) # $dim [1] 2 5

x # 2x5 matrix가 된다.

class(x) # matrix

dim(x) # 2 5


* 따라서 matrix는 vector에 dimension이 추가된 것으로 볼 수 있다.

* 또한 vector는 원소의 타입이 다 같아야한다. 이는 matrix와 array도 마찬가지이다.

* dataframe와 list는 "데이터를 폴더형태로 모아놓은 환경" 이라고 볼 수 있다. 근데 차이는 dataframe은 데이터들의 길이가 같아야하고 list는 데이터의 길이에서 자유롭다. 

* R에서 $는 무엇인가? 서로 다른 환경에 접근할 때 $라는 기호를 사용한다. 예를 들어 datat$var 과 같이 data라는 dataframe 내의 var라는 환경에 접근할 수 있다. 이는 list도 마찬가지이다.


x <- data.frame(a=1:10)

x$b <- 11:20 # 해당 컬럼에 값 할당

x$c <- rep(c('a','b'),5)) 

x$c <- as.factor(x$c) # 이렇게하면 factor로 변경된다.


* 처음 dataframe을 생성하고 변수값을 초기화할 때 string vector를 지정하면 그 string들은 자동으로 factor로 변환된다. 이 때, stringAsFactors=F로해야지 자동으로 factor로 변하지 않고 string으로 저장된다.


class(x) <- NULL

class(x) # list


으로 만들면, x의 class는 list가 된다.


Attach


search()

현재 존재하는 모든 공간을 나타내준다.


attach(x)

이러고 만약 x가 데이터프레임이고 a라는 컬럼이 있다면, 커맨드에 a만쳐도 a 컬럼에 있는 데이터에 접근할 수 있다. 만약 매번 x$a로 접근하는 것이 불편하다면 attach(x)를 통해 서치 공간에 a 컬럼을 추가할 수 있다.


detach(x)

서치공간에서 x를 제거한다.


Data Export


write.table(data, 'x.txt', sep='\t', quote=F, col.names=F, row.names=F) # quote는 문자열에 기본적으로 "를 넣을 것인가? col.names와 row.names는 각각 컬럼 이름과 로우 이름을 출력할지 말지를 나타낸다. 저장되는 위치는 getwd를 통해 알 수 있으며, setwd를 통해 현재 작업디렉토리를 변경할 수 있다.


Data Import


scan(file='a.txt') # (권장하지 않음)

read.table('a.txt', header=TRUE) # 일반적으로 이렇게 읽으며, 데이터프레임으로 읽는다. 또한, 문자열은 자동으로 factor로 변환한다.


만약 데이터를 임포트할 때, 경로를 찾기가 귀찮다면, file.choose()를 이용한다. 그러면 파일 탐색기 창이 뜨고 여기서 파일을 클릭하면 자동으로 해당 경로가 문자열로 나타나게 된다.


함수


f <- function(x, y) {

return(x+y)

}



R의 함수의 기본 문법은 위와 같다. 함수의 종류에도 여러개가 있는데 그 중 하나가 제네릭 함수이다. 예를 들어, summary(f)를 하면 그 함수에 대한 설명이 나온다. 반면, summary(c(1,2,3,4,5))를 하면, 해당 벡터를 연속형 변수로 치고 분포 관련 정보를 보여주게된다. 이는 methods(summary)를 통해 알 수 있다.


> methods(summary)
 [1] summary.aov                    summary.aovlist*             
 [3] summary.aspell*                summary.check_packages_in_dir*
 [5] summary.connection             summary.data.frame           
 [7] summary.Date                   summary.default              
 [9] summary.ecdf*                  summary.factor               
[11] summary.glm                    summary.infl*                
[13] summary.lm                     summary.loess*               
[15] summary.manova                 summary.matrix               
[17] summary.mlm*                   summary.nls*                 
[19] summary.packageStatus*         summary.PDF_Dictionary*      
[21] summary.PDF_Stream*            summary.POSIXct              
[23] summary.POSIXlt                summary.ppr*                 
[25] summary.prcomp*                summary.princomp*            
[27] summary.proc_time              summary.srcfile              
[29] summary.srcref                 summary.stepfun              
[31] summary.stl*                   summary.table                
[33] summary.tukeysmooth*         

이렇게 입력 클래스로 무엇이 들어오느냐에 따라 다른 실행을 한다. lm 클래스가 들어오면, 회귀분석 결과에 관한 요약을 해주고, aov가 들어오면 분산분석 결과에 관한 요약을 해준다.


히스토그램 그리기


x <- rnorm(5000, 1, 5000) # 임의 데이터 생성

> dd <- hist(x)
> class(dd)
[1] "histogram"
 
class(dd) <- NULL # 클래스를 NULL로 바꾸면 dd가 list가 된다.
dd # 이 dd 안에는 histogram을 그리기 위한 정보들이 들어있다.


$breaks
 [1] -18000 -16000 -14000 -12000 -10000  -8000  -6000  -4000  -2000      0
[11]   2000   4000   6000   8000  10000  12000  14000  16000  18000  20000

$counts
 [1]   4   9  33  75 155 269 512 665 763 803 619 526 292 156  79  29   8   2
[19]   1

$density
 [1] 4.00e-07 9.00e-07 3.30e-06 7.50e-06 1.55e-05 2.69e-05 5.12e-05 6.65e-05
 [9] 7.63e-05 8.03e-05 6.19e-05 5.26e-05 2.92e-05 1.56e-05 7.90e-06 2.90e-06
[17] 8.00e-07 2.00e-07 1.00e-07

$mids
 [1] -17000 -15000 -13000 -11000  -9000  -7000  -5000  -3000  -1000   1000
[11]   3000   5000   7000   9000  11000  13000  15000  17000  19000

$xname
[1] "x"

$equidist
[1] TRUE

R - 질적변수의 교호작용을 고려한 회귀모델

/* 2017.5.21  */


데이터의 형식은 아래와 같습니다.


  case gram weeks smoke

1    1 3147    40     0

2    2 2977    41     0

3    3 3119    38     0

4    4 3487    38     0

5    5 4111    39     0

6    6 3572    41     0


gram : 태아의 몸무게 

weeks : 임신주차

smoke : 임신기간 중 흡연 여부 



임신주차와 흡연여부 별로 태아의 몸무게가 어떻게 변하는지 설명하는 회귀식을 찾는 것입니다. 임신주차가 길 수록 태아의 몸무게는 무겁고, 흡연을 안할 수록 태아의 몸무게가 무겁다는 것을 예상해볼 수 있습니다.



이 때, smoke는 질적변수이며, 회귀모델을 구축하는 것에는 두 가지 종류가 있을 수 있습니다.



첫 번째는 smoke라는 질적변수에의해 회귀모델의 절편만 차이가 나는 경우

두 번째는 smoke라는 질적변수에 의해 절편과 기울기가 둘 다 차이가 나는 경우 (교호작용을 고려한 경우)



즉, 흡연여부에 의해 임신주차에 따른 태아의 몸무게의 변화가 영향을 주는 것까지 고려한 경우입니다.  이처럼 한 변수가 다른변수의 종속변수에 대한 효과에 영향을 끼치는 것을 다른말로 교호작용이라고 합니다. 예를 들어 흡연을 하는 경우, 임신주차에 따른 태아 몸무게의 증가 폭이 완만할 수 있겠죠.



두 번째 경우에 대해서만 R을 이용하여 모델을 구축하여보겠습니다.




data <- read.csv("C:/태아몸무게.csv") head(data) # 교호작용도 고려한 질적변수 처리 model2 <- lm(gram~weeks*smoke, data=data) coef <- coefficients(model2) inter <- coef[1] weeks <- coef[2] smoke <- coef[3] # 절편의 차이 weeks_smoke <- coef[4] # 기울기의 차 y1 <- inter+weeks*0:50 # non-smoker y2 <- inter+(weeks+weeks_smoke)*0:50+smoke # smoker plot(data$weeks, data$gram) lines(y1, col="red") lines(y2, col="blue")





  • model2 <- lm(gram~weeks*smoke, data=data) 라고하면 weeks와 smoke의 모든 경우에 수를 고려하여 회귀식을 만들겠다는 것입니다.
  • 그러면 weeks의 회귀계수(beta1)와 smoke의 회귀계수(beta2), weeks*smoke(beta3)의 회귀계수가 생기게 됩니다.
  • beta2는 smoke효과로 인한 절편의 차이이며, beta3는 smoke효과로 인한 기울기의 차이입니다.
  • 일반적인 모델에서는 beta3가 없고 절편의 차이만 있는데 교호작용까지 고려하면 기울기의 차이도 고려하는 것입니다.


결과




붉은색은 smoke=0 즉 비흡연자이고, 파란색은 smoke=1 즉 흡연자입니다. 흡연자는 임신주차가 증가하더라도 태아의 몸무게가 완만하게 증가하는 경향을 볼 수 있습니다. 절편값은 흡연자가 더 높은 것을 볼 수 있는데, 이것은 의미가 없습니다. (0주차에 출산하는 경우는 없기 때문) 절편의 효과를 보고 싶다면 centering 기법을 사용하면 됩니다.




R 단순회귀분석



단순회귀모형 만들기 코드



weight <- c(64,75.3,73,82.1,76.2,95.7,59.4,93.4,82.1,78.9,76.7,82.1,83.9,73,64.4,77.6) blood <- c(108,109,104,102,105,121,79,107,101,85,99,100,108,104,102,87) model <- lm(blood~weight) summary(model) # 회귀분석 결과 요약 anova(model) # anova table confint(model) # 회귀계수의 confidence interval




summary(model)의 결과



Residuals: ## 잔차정보 요약

     Min       1Q   Median       3Q      Max 

-17.0962  -2.9774   0.8138   5.5072  13.4990 


Coefficients:  ## 회귀계수의 추정과 회귀계수의 유의성 검정

            Estimate Std. Error t value Pr(>|t|)   

(Intercept)  61.8769    19.1890   3.225  0.00611 **

weight        0.5098     0.2462   2.070  0.05740 . 


F-statistic: 4.286 on 1 and 14 DF,  p-value: 0.0574      ## 모델이 유의한지에 대한 F-Test (분산분석)






anova(model)의 결과



Analysis of Variance Table


Response: blood

          Df Sum Sq Mean Sq F value Pr(>F)  

weight     1  368.8  368.80  4.2861 0.0574 .

Residuals 14 1204.6   86.05                 



  • ANOVA F-test의 p-value와 회귀계수에 대한 t-test의 p-value가 같다. (0.0574)
  • 또한 단순회귀분석에서는 모델이 유의한지에 대한 F-test의 p-value도 위의 p-value와 같다.



confint(model)의 결과



2.5 %     97.5 %

(Intercept) 20.7205466 103.033319

weight      -0.0183444   1.037845


  • 회귀계수의 confidence interval을 구할 수 있다.



Prediction



newdata <- data.frame(weight=95)
predict(model, newdata, interval="predict")
predict(model, newdata, interval="confidence")


  • weight=95일 때, blood의 값을 예측한다. 만약 여러개의 값을 예측하고 싶은경우는 weight=c(95,90,80, ...) 처럼 vector 형식으로 값을 주면 된다.
  • interval=prediction으로 하면 예측구간이고 interval=confidence로하면 신뢰구간이다.



Prediction 결과



 fit      lwr      upr

1 110.3032 87.77959 132.8269

  fit      lwr      upr

1 110.3032 99.74413 120.8623


  • fit이 예측값이고, lwr, upr은 각각 신뢰구간의 lower bound와 upper bound이다.
  • 위와 같이 예측구간과 신뢰구간을 구할 수 있다. 예측구간이 신뢰구간에 비해 넓다. 예측구간은 y에 대한 95% interval이고 신뢰구간은 E(y|x) 에 대한 95% interval이다. 따라서 예측구간이 신뢰구간에 비해 넓은 것이다.


(10) 리스트 (List)


List 만들기


List와 Vector의 차이점은 Vector는 한 가지 타입의 원소만 담을 수 있지만, List는 어떤 타입이든 담을 수 있다는 것이다.  List는 위와 같이 list() 키워드를 통해 만들 수 있다.


# Create a list containing strings, numbers, vectors and a logical values.
list_data <- list("Red", "Green", c(21,32,11), TRUE, 51.23, 119.1)
print(list_data)



[[1]]
[1] "Red"

[[2]]
[1] "Green"

[[3]]
[1] 21 32 11

[[4]]
[1] TRUE

[[5]]
[1] 51.23

[[6]]
[1] 119.1


출력해보면 위와 같이 첫 번째 원소는 String, 세 번째 원소는 Vector, 네 번째 원소는 진릿값인 것을 알 수 있다.



List에 이름 붙이기 


# Create a list containing a vector, a matrix and a list.
list_data <- list(c("Jan","Feb","Mar"), matrix(c(3,9,5,1,-2,8), nrow = 2),
   list("green",12.3))

# Give names to the elements in the list.
names(list_data) <- c("1st Quarter", "A_Matrix", "A Inner list")

# Show the list.
print(list_data)


$`1st Quarter`
[1] "Jan" "Feb" "Mar"

$A_Matrix
     [,1] [,2] [,3]
[1,]    3    5   -2
[2,]    9    1    8

$`A Inner list`
$`A Inner list`[[1]]
[1] "green"

$`A Inner list`[[2]]
[1] 12.3



위와 같은 문법을 통해 List의 각각의 원소에 이름을 붙일 수 있다. 



리스트 원소 접근


리스트에는 기본적으로 index를 통해 접근할 수 있고, 이름이 붙어져 있으면 이름으로도 접근할 수 있다. 이름으로 접근할 때는 $키워드를 통해 리스트의 이름을 명시해주면 된다.


# Create a list containing a vector, a matrix and a list.
list_data <- list(c("Jan","Feb","Mar"), matrix(c(3,9,5,1,-2,8), nrow = 2),
   list("green",12.3))

# Give names to the elements in the list.
names(list_data) <- c("1st Quarter", "A_Matrix", "A Inner list")

# Access the first element of the list.
print(list_data[1])

# Access the thrid element. As it is also a list, all its elements will be printed.
print(list_data[3])

# Access the list element using the name of the element.
print(list_data$A_Matrix)


$`1st Quarter`
[1] "Jan" "Feb" "Mar"

$`A Inner list`
$`A Inner list`[[1]]
[1] "green"

$`A Inner list`[[2]]
[1] 12.3


     [,1] [,2] [,3]
[1,]    3    5   -2
[2,]    9    1    8



리스트 원소 조작하기 (Manipulating)


리스트 원소 조작은 아래와 같이 <- 키워드를 통해 새로운 값을 넣어주면 된다.


# Create a list containing a vector, a matrix and a list.
list_data <- list(c("Jan","Feb","Mar"), matrix(c(3,9,5,1,-2,8), nrow = 2),
   list("green",12.3))

# Give names to the elements in the list.
names(list_data) <- c("1st Quarter", "A_Matrix", "A Inner list")

# Add element at the end of the list.
list_data[4] <- "New element"
print(list_data[4])

# Remove the last element.
list_data[4] <- NULL

# Print the 4th Element.
print(list_data[4])

# Update the 3rd Element.
list_data[3] <- "updated element"
print(list_data[3])

[[1]]
[1] "New element"

$<NA>
NULL

$`A Inner list`
[1] "updated element"


리스트 합치기


아래와 같이 c() 키워드를 통해 리스트를 합칠 수 있다. 


# Create two lists.
list1 <- list(1,2,3)
list2 <- list("Sun","Mon","Tue")

# Merge the two lists.
merged.list <- c(list1,list2)

# Print the merged list.
print(merged.list)


[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

[[4]]
[1] "Sun"

[[5]]
[1] "Mon"

[[6]]
[1] "Tue"


리스트를 벡터로 변환하기


List 상태에서는 벡터 상태에서 보다 조작의 자유도가 떨어진다. 예를 들어 산술 연산을 한다거나 할 수 없다. 다양한 조작을 위해 리스트를 벡터로 변환할 때는 아래와 같이 unlist() 키워드를 이용하면 된다. 


# Create lists.
list1 <- list(1:5)
print(list1)

list2 <-list(10:14)
print(list2)

# Convert the lists to vectors.
v1 <- unlist(list1)
v2 <- unlist(list2)

print(v1)
print(v2)

# Now add the vectors
result <- v1+v2
print(result)


[[1]]
[1] 1 2 3 4 5

[[1]]
[1] 10 11 12 13 14

[1] 1 2 3 4 5
[1] 10 11 12 13 14
[1] 11 13 15 17 19



아래 튜토리얼을 참고한 포스팅입니다.


https://www.tutorialspoint.com/r/r_lists.htm

'Hard skills > R' 카테고리의 다른 글

R - 질적변수의 교호작용을 고려한 회귀모델  (0) 2017.05.21
R - 단순회귀분석  (0) 2017.05.21
R - (10) 리스트(List)  (0) 2017.03.04
R 통계 분석 - 평균, 중앙값, 최빈값 (Mean, Median, Mode)  (0) 2017.02.23
R - (9) 벡터  (0) 2017.02.23
R - (8) 문자열 (Strings)  (0) 2017.02.23


R 통계분석 Mean, Median, Mode


R을 통한 통계분석은 많은 in-built 함수들을 통해 이루어진다. 이러한 함수들은 대부분 R base package에 속해있고, vector들을 다른 argument들과 함께 input으로 받아 결과를 출력해준다. 이번 포스팅에 다룰 내용은 mean, median, mode 함수이다. 



1. Mean 


문법 


mean(x, trim = 0, na.rm = FALSE, ...)


  • x : input vector
  • trim : 정렬된 vector에서 양 극단에서의 일정 부분을 뺄 때 사용함
  • na.rm : missing value를 제거하고 계산할 때 사용

예제

# Create a vector. 
x <- c(12,7,3,4.2,18,2,54,-21,8,-5)

# Find Mean.
result.mean <- mean(x)
print(result.mean)


[1] 8.22



Trim Option 사용하기


# Create a vector.
x <- c(12,7,3,4.2,18,2,54,-21,8,-5)

# Find Mean.
result.mean <-  mean(x,trim = 0.3)
print(result.mean)


Trim을 사용하면 양 극단에서 일정부분을 빼고 계산한다. 0.3일 경우 양 끝에서 전체 데이터의 0.3 만큼을 제외한다. 이 경우에 전체데이터가 10개이므로 양 끝에서 3개씩을 뺀다. 즉 정렬된 벡터 (−21, −5, 2, 3, 4.2, 7, 8, 12, 18, 54) 에서 (−21,−5,2) (12,18,54) 을 뺀 평균을 계산한다. 



NA 옵션 적용하기


# Create a vector. 
x <- c(12,7,3,4.2,18,2,54,-21,8,-5,NA)

# Find mean.
result.mean <-  mean(x)
print(result.mean)

# Find mean dropping NA values.
result.mean <-  mean(x,na.rm = TRUE)
print(result.mean)


[1] NA
[1] 8.22


원래는 오류가 날 것을 na.rm=TRUE 를 통해 NA 값을 제거하고 평균을 구할 수 있다.



2. Median


Median(중위수)는 전체 데이터에서 중앙에 있는 값을 뜻한다. Median() 함수는 이 값을 구하기 위해 사용된다.


문법 


median(x, na.rm = FALSE)



# Create the vector.
x <- c(12,7,3,4.2,18,2,54,-21,8,-5)

# Find the median.
median.result <- median(x)
print(median.result)



3. Mode 


Mode(최빈값)은 데이터에서 가장 많이 등장한 값이다. 안타깝게도 R에는 Mode를 구하는 in-built function이 없다. 직접 정의한 getmode() 함수를 통해 Mode를 구해보자.


# Create the function.
getmode <- function(v) {
   uniqv <- unique(v)
   uniqv[which.max(tabulate(match(v, uniqv)))]
}

# Create the vector with numbers.
v <- c(2,1,2,3,1,2,3,4,1,5,5,3,2,3)

# Calculate the mode using the user function.
result <- getmode(v)
print(result)

# Create the vector with characters.
charv <- c("o","it","the","it","it")

# Calculate the mode using the user function.
result <- getmode(charv)
print(result)


[1] 2
[1] "it"



이렇게 정의된 getmode 함수는 위처럼 문자열에도 적용할 수 있다.



아래 튜토리얼을 참고한 포스팅입니다.

https://www.tutorialspoint.com/r/r_mean_median_mode.htm

'Hard skills > R' 카테고리의 다른 글

R - 단순회귀분석  (0) 2017.05.21
R - (10) 리스트(List)  (0) 2017.03.04
R 통계 분석 - 평균, 중앙값, 최빈값 (Mean, Median, Mode)  (0) 2017.02.23
R - (9) 벡터  (0) 2017.02.23
R - (8) 문자열 (Strings)  (0) 2017.02.23
R을 통한 2017년 대선 주자들 페이스북 분석  (5) 2017.02.21

Hard skills/R

R - (9) 벡터

2017. 2. 23. 16:37

(9) 벡터 (Vectors)


벡터는 가장 기본적인 R의 Data Object이다. 우선 기본적으로 6개의 atomic vector들을 알아야할 필요가 있다.  이 6개의 atomic vectors는 이전 포스팅 에도 소개하였지만, logical, integer, double, complex, character, raw이다. 아래의 예를 통해 복습하자.


# Atomic vector of type character.
print("abc");

# Atomic vector of type double.
print(12.5)

# Atomic vector of type integer.
print(63L)

# Atomic vector of type logical.
print(TRUE)

# Atomic vector of type complex.
print(2+3i)

# Atomic vector of type raw.
print(charToRaw('hello'))


1. 벡터의 원소에 접근하기


벡터의 원소에는 인덱스를 통해 접근할 수 있다. [](brackets) 이 인덱싱을 위해 필요하다. 인덱싱은 다른 프로그래밍 언어와는 다르게 1부터 시작한다.  또한 - 인덱싱은 해당 엘리먼트를 결과값에서 제외한다는 뜻이다. TRUE, FALSE, 0, 1도 인덱싱을 위해 사용될 수 있다. 아래의 예를 보자.


# Accessing vector elements using position.
t <- c("Sun","Mon","Tue","Wed","Thurs","Fri","Sat")
u <- t[c(2,3,6)]
print(u)

# Accessing vector elements using logical indexing.
v <- t[c(TRUE,FALSE,FALSE,FALSE,FALSE,TRUE,FALSE)]
print(v)

# Accessing vector elements using negative indexing.
x <- t[c(-2,-5)]
print(x)

# Accessing vector elements using 0/1 indexing.
y <- t[c(0,0,0,0,0,0,1)]
print(y)


[1] "Mon" "Tue" "Fri"
[1] "Sun" "Fri"
[1] "Sun" "Tue" "Wed" "Fri" "Sat"
[1] "Sun"



2. 벡터 조작하기


(1) 벡터 연산


길이가 같은 벡터들은 더하고, 빼고, 곱하고, 나누고 할 수 있다.


# Create two vectors.
v1 <- c(3,8,4,5,0,11)
v2 <- c(4,11,0,8,1,2)

# Vector addition.
add.result <- v1+v2
print(add.result)

# Vector substraction.
sub.result <- v1-v2
print(sub.result)

# Vector multiplication.
multi.result <- v1*v2
print(multi.result)

# Vector division.
divi.result <- v1/v2
print(divi.result)



[1]  7 19  4 13  1 13
[1] -1 -3  4 -3 -1  9
[1] 12 88  0 40  0 22
[1] 0.7500000 0.7272727       Inf 0.6250000 0.0000000 5.5000000



(2) 벡터 엘리먼트 재사용


만약 두 개의 벡터를 연산하려는데 길이가 다르면, 짧은 쪽의 벡터의 원소가 재사용된다.


v1 <- c(3,8,4,5,0,11)
v2 <- c(4,11)
# V2 becomes c(4,11,4,11,4,11)

add.result <- v1+v2
print(add.result)

sub.result <- v1-v2
print(sub.result)


[1]  7 19  8 16  4 22
[1] -1 -3  0 -6 -4  0

위의 결과를 보면 v2가 (4,11) 에서 (4,11,4,11,4,11)로 바뀌었음을 알 수 있다. 연산을 하기 위해 (4,11)이 재사용된 것이다.



(3) 벡터 엘리먼트 정렬


벡터들의 엘리먼트는 sort() 함수를 통해 정렬될 수 있다.


v <- c(3,8,4,5,0,11, -9, 304)

# Sort the elements of the vector.
sort.result <- sort(v)
print(sort.result)

# Sort the elements in the reverse order.
revsort.result <- sort(v, decreasing = TRUE)
print(revsort.result)

# Sorting character vectors.
v <- c("Red","Blue","yellow","violet")
sort.result <- sort(v)
print(sort.result)

# Sorting character vectors in reverse order.
revsort.result <- sort(v, decreasing = TRUE)
print(revsort.result)


[1]  -9   0   3   4   5   8  11 304
[1] 304  11   8   5   4   3   0  -9
[1] "Blue"   "Red"    "violet" "yellow"
[1] "yellow" "violet" "Red"    "Blue"  




'Hard skills > R' 카테고리의 다른 글

R - (10) 리스트(List)  (0) 2017.03.04
R 통계 분석 - 평균, 중앙값, 최빈값 (Mean, Median, Mode)  (0) 2017.02.23
R - (9) 벡터  (0) 2017.02.23
R - (8) 문자열 (Strings)  (0) 2017.02.23
R을 통한 2017년 대선 주자들 페이스북 분석  (5) 2017.02.21
R - (7) 함수  (0) 2017.02.19
(8) 문자열 (Strings)


R에서 쌍따옴표나 작은 따옴표로 둘러쌓인것은 문자열로 취급된다. 


문자열을 만들 때 주의할점

  • 문자열은 만들 때, 쌍따옴표 혹은 작은따옴표만을 사용하여야한다. 두개를 혼합하여 사용하면 안된다.
  • 쌍따옴표는 작은따옴표 사이에 들어갈 수 잇다.
  • 작은 따옴표는 쌍따옴표 사이에 들어갈 수 있다.
  • 쌍따옴표는 쌍따옴표 사이에 들어갈 수 없다.
  • 작은따옴표는 작은따옴표 사이에 들어갈 수 없다.

적절한 문자열들의 예

a <- 'Start and end with single quote'
print(a)

b <- "Start and end with double quotes"
print(b)

c <- "single quote ' in between double quotes"
print(c)

d <- 'Double quotes " in between single quote'
print(d)


[1] "Start and end with single quote"
[1] "Start and end with double quotes"
[1] "single quote ' in between double quotes"
[1] "Double quotes \" in between single quote"


부적절한 문자열들의 예

e <- 'Mixed quotes" 
print(e)

f <- 'Single quote ' inside single quote'
print(f)

g <- "Double quotes " inside double quotes"
print(g)


문자열 조작(manipulation)

1. paste()

설명 : 두 개의 문자열을 연결(Concatenating)할 때 사용한다.
문법 : paste(..., sep = " ", collapse = NULL)

예 : 

a <- "Hello"
b <- 'How'
c <- "are you? "

print(paste(a,b,c))

print(paste(a,b,c, sep = "-"))

print(paste(a,b,c, sep = "", collapse = ""))

[1] "Hello How are you? "
[1] "Hello-How-are you? "
[1] "HelloHoware you? "

2. format()

설명 : 문자나 숫자를 원하는 포맷으로 변경한다.

문법 : format(x, digits, nsmall, scientific, width, justify = c("left", "right", "centre", "none"))

  • x : 벡터 input
  • digits : 출력할 총 자릿수
  • nsmall : 소숫점 우측의 최소 자릿수
  • scientific : TRUE이면 scientific notation을 함
  • width : 최소 width (왼쪽에 blank를 넣어 width를 맞춘다.)
  • justify : 정렬할 위치 (좌측정렬, 가운데 정렬, 우측정렬)

# Total number of digits displayed. Last digit rounded off.
result <- format(23.123456789, digits = 9)
print(result)

# Display numbers in scientific notation.
result <- format(c(6, 13.14521), scientific = TRUE)
print(result)

# The minimum number of digits to the right of the decimal point.
result <- format(23.47, nsmall = 5)
print(result)

# Format treats everything as a string.
result <- format(6)
print(result)

# Numbers are padded with blank in the beginning for width.
result <- format(13.7, width = 6)
print(result)

# Left justify strings.
result <- format("Hello", width = 8, justify = "l")
print(result)

# Justfy string with center.
result <- format("Hello", width = 8, justify = "c")
print(result)

[1] "23.1234568"
[1] "6.000000e+00" "1.314521e+01"
[1] "23.47000"
[1] "6"
[1] "  13.7"
[1] "Hello   "
[1] " Hello  "

3. nchar()

설명 : 문자의 갯수를 세준다. (공백도 포함한다.)
예 :

result <- nchar("Count the number of characters")
print(result)

[1] 30


4. toupper(), tolower()

설명 : 문자열을 대문자로 바꾼다 / 문자열을 모두 소문자로 바꾼다.

생략 

5. substring()

설명 : 문자열의 일부를 추출한다.
문법 : substring(x,first,last)
예 : 

# Extract characters from 5th to 7th position.
result <- substring("Extract", 5, 7)
print(result)

[1] "act"

아래 튜토리얼을 참고한 포스팅입니다. 

https://www.tutorialspoint.com/r/r_operators.htm 



'Hard skills > R' 카테고리의 다른 글

R 통계 분석 - 평균, 중앙값, 최빈값 (Mean, Median, Mode)  (0) 2017.02.23
R - (9) 벡터  (0) 2017.02.23
R - (8) 문자열 (Strings)  (0) 2017.02.23
R을 통한 2017년 대선 주자들 페이스북 분석  (5) 2017.02.21
R - (7) 함수  (0) 2017.02.19
R - (6) 반복문  (0) 2017.02.17

R 연습도 할겸, 재미로 대선 주자들(문재인, 이재명, 안희정, 황교안, 안철수, 유승민) 총 6명의 페이스북 페이지를 분석해 보았습니다. 분석에는 R을 사용하였고 Facebook API를 구현한 Rfacebook 패키지를 이용하였습니다. 


2016년 11월 1일 ~ 2016년 2월 19일 분석 기간으로 정하였고, 총 3가지에 관하여 분석해보았습니다. 


  • 총 포스팅 횟수
  • 포스팅당 평균 좋아요 수
  • 날짜별 좋아요수 변화 그래프 


총 포스팅 횟수




총 포스팅 횟수는 이재명-안철수-문재인 순으로 나타났습니다. 이재명과 안철수가 해당 기간 (2016년 11월 1일 ~ 2017년 2월 19일) 동안 300개가 넘는 포스팅으로 나란히 1, 2위를 차지하였고, 페이스북 포스팅에 적극적인 모습을 보였습니다. 반면 6등인 황교안은 83 포스팅으로 가장 적은 포스팅을 하였습니다.



포스팅당 평균 좋아요 수





포스팅당 평균 좋아요수는 위와 같이 나타났습니다. 문재인이 포스팅당 6146로 다른 후보들과 비교하여 압도적인 좋아요수를 기록하였고 2위인 안희정과 비교하여 거의 2배의 평균 좋아요 수를 보였습니다. 이를 실제 대선 주자 지지도 조사와 비교하여볼까요?






리얼미터에서 조사한 대선후보 지지율은 위와 같습니다. 문재인-안희정-황교안-안철수-이재명-유승민 순입니다. 페이스북 페이지 평균 좋아요수는 문재인-안희정-황교안-이재명-안철수-유승민 순으로 단순 순위만 봤을 때 안철수, 이재명의 차이만 빼고는 같다는 것을 알 수 있습니다. 이를 해석해보면 이재명은 페이스북에서 비교적 인기가 많다고도 볼 수 있을것 같습니다. 주로 20, 30대들이 페이스북을 많이하니 20, 30대들이 좋아하는 이재명이 페이스북에서 강세를 보이는 것으로 보입니다.



날짜별 좋아요수 변화 그래프





다음은 날짜별로 좋아요 수가 어떻게 변하는지 그래프를 그려보았는데요. 자세히 보시면 문재인 후보의 좋아요수가 평균적으로 점점 감소해가는 것을 볼 수 있습니다. 또한 자세히 보시면 안희정 후보들의 포스팅에서 최근들어 좋아요를 많이 받은 포스팅이 점점 많아지는 것이 보입니다. 다른 후보들에서는 생각외로 뚜렷한 패턴을 발견할 수 없어보이네요.



이러한 분석을 통해 대선 결과를 예측하거나 할 수는 없을 것 같습니다. 단순한 통계 분석에 그치기 때문입니다. 그냥 재미로 봐주셨으면 좋겠습니다. 하지만 최근 많이 사용하는 텍스트 마이닝, 감정 분석등의 머신러닝 알고리즘을 통해 네티즌들의 반응, 포스팅 내용 등을 분석하면 조금 더 깊고 의미있는 통찰을 할 수 있을 것입니다.



제가 사용한 R 코드는 아래에 첨부합니다. 


facebook.R


# https://cran.r-project.org/web/packages/Rfacebook/Rfacebook.pdf
library(Rfacebook)
library(ggplot2)
library(scales)
# get auth token
fb_oauth = fbOAuth(app_id = "310016876042099", app_secret = "6772bfc30e27720eac8d67122157aa47", extended_permissions = FALSE)

# 해당 페이지의 시작날짜와 종료날짜 사이의 모든 포스트 가져옴
getPosts <- function(page_name, start_date, end_date) {
  # 날짜 sequence
  scrape_days <- seq(from=as.Date(start_date), to=as.Date(end_date), by='days')
  posts = c()
  for(scrape_day in scrape_days){
    daypost = c()
    tryCatch({
      daypost = getPage(page=page_name, token=fb_oauth,
                        since=as.Date(scrape_day, origin='1970-01-01'),
                        until=as.Date(scrape_day, origin='1970-01-01')+1)},
      error = function(e){})
    posts = rbind(posts, daypost)
  }
  return(posts)
}

drawLikeGraph <- function(data){
  ggplot(data, aes(x=created_time, y=likes_count)) + geom_line() + 
    theme_bw() + scale_x_date(labels = date_format("%m-%Y")) +
    labs(x = "날짜(MM-yyyy)", y = "좋아요수(n)") + 
    ggtitle(paste(start_date, end_date, sep="~"))
}

drawPostNumGraph <- function(data){
  ggplot(data=data, aes(x=name, y=num, fill=name)) +
    geom_bar(stat="identity", width=0.8) +
    labs(x='대선주자', y='포스트수') +
    geom_text(aes(label=num), vjust=1.6, color="white", size=3.5) +
    theme_minimal() +
    ggtitle(paste(start_date, end_date, sep="~"))
}

drawAverageLikeGraph <- function(data){
  ggplot(data=data, aes(x=name, y=average_like, fill=name)) +
    geom_bar(stat="identity", width=0.8) +
    labs(x='대선주자', y='평균 좋아요수') +
    geom_text(aes(label=round(average_like, 0)), vjust=1.6, color="white", size=3.5) +
    theme_minimal() +
    ggtitle(paste(start_date, end_date, sep="~"))
}

getSummaryDataFrame <- function(posts, name){
  average_like = sum(posts$likes_count)/nrow(posts)
  summary <- data.frame(name=name, num=nrow(posts),
                        average_like=average_like)
  return(summary)
}

moon_page = "moonbyun1" # 문재인 페이지 
lee_page = "jaemyunglee1" # 이재명 페이지
hwang_page = "PM0415HwangKyoahn" # 황교안 페이지
yoo_page = "yooseongmin21" # 유승민 페이지
ahn_hwee_page = "steelroot" # 안희정 페이지
ahn_chul_page = "ahncs111" # 안철수 페이

start_date <- '2016/11/01' # 시작 날짜
end_date <- '2017/02/19' # 종료 날짜

moon_posts <- getPosts(moon_page, start_date, end_date)
lee_posts <- getPosts(lee_page, start_date, end_date)
hwang_posts <- getPosts(hwang_page, start_date, end_date)
yoo_posts <- getPosts(yoo_page, start_date, end_date)
ahn_hwee_posts <- getPosts(ahn_hwee_page, start_date, end_date)
ahn_chul_posts <- getPosts(ahn_chul_page, start_date, end_date)

print(nrow(hwang_posts))

# preprocess
moon_posts$created_time <- as.Date(moon_posts$created_time) # string to date
lee_posts$created_time <- as.Date(lee_posts$created_time)
hwang_posts$created_time <- as.Date(hwang_posts$created_time)
yoo_posts$created_time <- as.Date(yoo_posts$created_time)
ahn_hwee_posts$created_time <- as.Date(ahn_hwee_posts$created_time)
ahn_chul_posts$created_time <- as.Date(ahn_chul_posts$created_time)

# summary 데이터 프레임 만듦
moon_summary <- getSummaryDataFrame(moon_posts, '문재인')
lee_summary <- getSummaryDataFrame(lee_posts, '이재명')
hwang_summary <- getSummaryDataFrame(hwang_posts, '황교안')
yoo_summary <- getSummaryDataFrame(yoo_posts, '유승민')
ahn_hwee_summary <- getSummaryDataFrame(ahn_hwee_posts, '안희정')
ahn_chul_summary <- getSummaryDataFrame(ahn_chul_posts, '안철수')

summary <- data.frame() # 빈 데이터 프레임을 만듦
summary <- rbind(summary, moon_summary) # 행추가
summary <- rbind(summary, lee_summary)
summary <- rbind(summary, hwang_summary)
summary <- rbind(summary, yoo_summary)
summary <- rbind(summary, ahn_hwee_summary)
summary <- rbind(summary, ahn_chul_summary)

drawPostNumGraph(summary)
drawAverageLikeGraph(summary)

# reactions <- getReactions(post=posts$id, fb_oauth, verbose=TRUE)
drawLikeGraph(moon_posts)
drawLikeGraph(lee_posts)
drawLikeGraph(hwang_posts)
drawLikeGraph(yoo_posts)
drawLikeGraph(ahn_hwee_posts)
drawLikeGraph(ahn_chul_posts)

all_posts <- data.frame()
all_posts <- rbind(all_posts, moon_posts)
all_posts <- rbind(all_posts, lee_posts)
all_posts <- rbind(all_posts, hwang_posts)
all_posts <- rbind(all_posts, yoo_posts)
all_posts <- rbind(all_posts, ahn_hwee_posts)
all_posts <- rbind(all_posts, ahn_chul_posts)

ggplot(all_posts, aes(x=created_time, y=likes_count, group=from_name, colour=from_name)) + geom_line(size=0.5) + 
  geom_smooth() +
  theme_minimal() + scale_x_date(labels = date_format("%m-%Y")) +
  labs(x = "날짜(MM-yyyy)", y = "좋아요수(n)") + 
  ggtitle(paste(start_date, end_date, sep="~"))


'Hard skills > R' 카테고리의 다른 글

R - (9) 벡터  (0) 2017.02.23
R - (8) 문자열 (Strings)  (0) 2017.02.23
R을 통한 2017년 대선 주자들 페이스북 분석  (5) 2017.02.21
R - (7) 함수  (0) 2017.02.19
R - (6) 반복문  (0) 2017.02.17
R - (5) If, else if, switch  (0) 2017.02.15
  • kms 2017.06.13 15:25

    해당 페이지의 시작날짜와 종료날짜 사이의 모든 포스트 가져옴의 URL는 어떻게 지정하나요?

    • Deepplay 2017.06.14 14:43 신고

      각 페이스북 페이지 URL에는 페이지명을 나타내는 이름이 있습니다. 그걸 Rfacebook의 getPage함수의 page 파라미터로 전달하시면 됩니다. 즉, URL이 아니라 페이스북 페이지 이름을 전달하시면됩니다! 그리고 since와 until 파라미터를 넣으면 그 사이의 포스트를 가져오게됩니다.

  • study 2018.12.05 13:32

    이게지금은 안돌아가나요? 프로그램돌리면 데이터가 안들어오는데 ..

    • Deepplay 2018.12.05 15:07 신고

      안녕하세요.
      app_id, app_secret 을 직접 받아서 fbOAuth 함수에 넣어줘야 하는걸로 기억합니다.

  • 2020.12.29 20:26

    비밀댓글입니다

Hard skills/R

R - (7) 함수

2017. 2. 19. 02:29

(7) 함수


함수는 특정한 태스크를 하기 위한 구문들의 집합이다. R에는 in-built 함수들이 많이 있고 또한 직접 함수를 정의하여 사용할 수도 있다. 한 가지 주의할 점은 R에서 함수는 객체이다. 



함수 정의


R에서 함수는 function() 키워드를 통해 만들 수 있다.


function_name <- function(arg_1, arg_2, ...) {
   Function body 
}



함수의 구성요소 


  • Function Name : 함수의 실제 이름이다. R environment에 해당 이름의 객체로 저장된다. 
  • Arguments : Arguments는 placeholder이다. 함수가 호출 될 때, arguments에 값이 할당된다. arguments는 없어도 되며, 또한 default 값을 가질 수 있다.
  • Function Body : function이 하는 일을 기술한 구문들이다.
  • Return Value : function body가 최종적으로 리턴한 값이다.


Built-in 함수


in-built 함수의 간단한 예에는 seq(), mean(), max(), sum() 등이 있다.


더 많은 in-built function 보기

https://cran.r-project.org/doc/contrib/Short-refcard.pdf 


# Create a sequence of numbers from 32 to 44.
print(seq(32,44))

# Find mean of numbers from 25 to 82.
print(mean(25:82))

# Find sum of numbers frm 41 to 68.
print(sum(41:68))



사용자 정의 함수


사용자 정의 함수의 예이다.


# Create a function to print squares of numbers in sequence.
new.function <- function(a) {
   for(i in 1:a) {
      b <- i^2
      print(b)
   }
}   
# Call the function new.function supplying 6 as an argument.
new.function(6)


다음과 같이 argument의 이름을 명시적으로 지정하여 호출할 수도 있다.


# Create a function with arguments.
new.function <- function(a,b,c) {
   result <- a * b + c
   print(result)
}

# Call the function by position of arguments.
new.function(5,3,11)

# Call the function by names of the arguments.
new.function(a = 11, b = 5, c = 3)



Default 값

다음과 같이 함수 내부에 default 값을 선언할 수도 있다. argument가 아무것도 주어지지 않는다면 default 값을 사용한다.


# Create a function with arguments.
new.function <- function(a = 3, b = 6) {
   result <- a * b
   print(result)
}

# Call the function without giving any argument.
new.function()

# Call the function with giving new values of the argument.
new.function(9,5)


아래 튜토리얼을 참고한 포스팅입니다. 

https://www.tutorialspoint.com/r/r_operators.htm 

'Hard skills > R' 카테고리의 다른 글

R - (8) 문자열 (Strings)  (0) 2017.02.23
R을 통한 2017년 대선 주자들 페이스북 분석  (5) 2017.02.21
R - (7) 함수  (0) 2017.02.19
R - (6) 반복문  (0) 2017.02.17
R - (5) If, else if, switch  (0) 2017.02.15
R - (4) 연산자  (0) 2017.02.15