행렬(matrix)와 배열(array) 을 이용한 R 적용

 R에서 행렬(matrix)와  배열(array)를 쓰는 이유는 연산 속도의 사유로 많이 사용하게 된다.  dataframe으로 된  데이터 셋을 연산하게 되면 속도가 매우 느린 현상이 발생 하게 된다.   R에서 멀티코어 코딩을 하려면,  반드시 알고 넘어가야 하는 것이 행렬(matrix)와 배열(array)이다. 


행렬과 배열

배열은 다차원 개체다. 배열의 차원은 dim 속성을 사용해 각 차원에 대한 최대값으로 설정 합니다.. 따라서 1부터 24까지 24개의 숫자로 구성된 3차원 배월 (2X3X3)에 대해 다음과 같이 명령을 작성 합니다.

y<-1:24
dim(y) <- c(2,4,3)
y
## , , 1
## 
##      [,1] [,2] [,3] [,4]
## [1,]    1    3    5    7
## [2,]    2    4    6    8
## 
## , , 2
## 
##      [,1] [,2] [,3] [,4]
## [1,]    9   11   13   15
## [2,]   10   12   14   16
## 
## , , 3
## 
##      [,1] [,2] [,3] [,4]
## [1,]   17   19   21   23
## [2,]   18   20   22   24

세번째 차원의 값이 3이므로 명령을 실행하면 3개의 2차원 테이블을 얻게 됩니다. 차원을 변경 하면 다음과 같습니다.

dim(y)<-c(3,2,4)
y
## , , 1
## 
##      [,1] [,2]
## [1,]    1    4
## [2,]    2    5
## [3,]    3    6
## 
## , , 2
## 
##      [,1] [,2]
## [1,]    7   10
## [2,]    8   11
## [3,]    9   12
## 
## , , 3
## 
##      [,1] [,2]
## [1,]   13   16
## [2,]   14   17
## [3,]   15   18
## 
## , , 4
## 
##      [,1] [,2]
## [1,]   19   22
## [2,]   20   23
## [3,]   21   24

변경 결과 3개의 행과 2개의 열을 갖는 이차원 테이블 4개를 얻을 수 있습니다. 두 가지 예를 살펴 보고 이를 정확히 이해해 봅시다. 행렬은 숫자를 내용으로 하는 이차원 배열 입니다. 데이터 프레임은 서로 다른 열에 숫자나 텍스트, 논리 변수가 포함된 데이터 유형을 갖고 있는 이차원 리스트 입니다. 행렬이나 데이터 프레임같은 개체에 대해 2개의 첨자[5,3]이 있는 경우, 첫 번째 첨자는 행의 번호를 의미하고, 두번째 첨자를 열의 번호를 의미합니다. 따라서 [5,3]에서 5는 행을 의미하고 3은 열을 의미합니다. R에서 가장 중요하고 강력한 규책으로 공백 첨자는 모든 데이터를 의미 합니다. 따라서 다음과 같습니다.

  • [.4]는 4열의 모든 행을 의미 합니다.
  • [2.]는 2행의 모든 열을 의미 합니다.



2.8.1 행렬

행렬을 만들기 위한 방법에는 여러가지가 있으며 다음과 같이 직접 만들수 있습니다.

X<-matrix(c(1,0,0,0,1,0,0,0,1), nrow = 3)
X
##      [,1] [,2] [,3]
## [1,]    1    0    0
## [2,]    0    1    0
## [3,]    0    0    1

기본 설정 사애에서 숫자는 열방향으로 입력이 됩니다.. X의 클래스와 속성은 dim의 속성값인 3개의 행과 3개의 열로 구성되어 있으며 이값은 dim 함수의 속성값이 됩니다.

class(X)
## [1] "matrix" "array"
attributes(X)
## $dim
## [1] 3 3

다음 예제에서 벡터 테이터는 행방향으로 표시하기 위해 byrow의 속성값을 T 설정 하였습니다.

vector<-c(1,2,3,4,4,3,2,1)
V<-matrix(vector, byrow = T, nrow = 2)
V
##      [,1] [,2] [,3] [,4]
## [1,]    1    2    3    4
## [2,]    4    3    2    1

벡터를 행렬로 변환하는 또다른 방법은 다음과 같이 대상 벡터 개체에 대해 dim 함수를 이용해 이차원 행과 열의 값을 설정 하는 것입니다.

dim(vector)<-c(4,2)

이제 벡터는 행렬이 되었습니다.

is.matrix(vector)
## [1] TRUE

행렬로 변환하는 과정에서 데이터는 입력되지 않았으므로 주의하도록 합니다.

vector
##      [,1] [,2]
## [1,]    1    4
## [2,]    2    3
## [3,]    3    2
## [4,]    4    1

행과 열 변환을 위해 전치행렬 t를 사용합니다.

(vector<-t(vector))
##      [,1] [,2] [,3] [,4]
## [1,]    1    2    3    4
## [2,]    4    3    2    1



2.8.2 행렬의 행과 열에 이름 지정

앞의 실행 결과처럼 행렬은 행과 열(위 참조)에 대해 숫자로 이름을 붙이기로 하였습니다. 다음은 평균 1.5인 포아송 분포에서 추출한 임의의 정수로 구성된 4X5 행렬 입니다.

X <- matrix(rpois(20,1.5), nrow = 4)
X
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    4    2    0    2
## [2,]    0    4    2    1    1
## [3,]    1    2    1    2    1
## [4,]    0    1    6    3    1

행은 4개의 다른 시도를 표현한다고 가정 합시다. 그리고 행을 시도 횟수 데이터라고 하며 Traial.1로 호칭 한다고 합시다. 이를 위해서는 rownames 함수를 사용합니다.

rownames(X) <- rownames(X,do.NULL=FALSE, prefix = "Trial.")
X
##         [,1] [,2] [,3] [,4] [,5]
## Trial.1    1    4    2    0    2
## Trial.2    0    4    2    1    1
## Trial.3    1    2    1    2    1
## Trial.4    0    1    6    3    1

특정 시도에 관련된 5개의 의학품 이름 벡터를 생성한 후 이값을 colnames(x)에 설정 합니다.

drug.names <- c("aspirin","paracetamol", "nerofen", "hedex", "placebo")
colnames(X) <- drug.names
X
##         aspirin paracetamol nerofen hedex placebo
## Trial.1       1           4       2     0       2
## Trial.2       0           4       2     1       1
## Trial.3       1           2       1     2       1
## Trial.4       0           1       6     3       1

또는 dimnames 함수를 사용해 행렬의 행과 열의 이름을 설정 할 수 있습니다. 이번 예제에서 행에는 표시를 붙이지 않고 열에는 drug.1, drug.2 등의 형태를 갖도록 합니다. dimnames에 대한 인자는 예제에서와 같이 길이 4와 5를 갖는 리스트 요소로 구성된 리스트(일반적으로 행이 첫번째, 열이 두 번째)여야 합니다.

dimnames(X)<-list(NULL,paste("drug.", 1:5, sep = ""))
X
##      drug.1 drug.2 drug.3 drug.4 drug.5
## [1,]      1      4      2      0      2
## [2,]      0      4      2      1      1
## [3,]      1      2      1      2      1
## [4,]      0      1      6      3      1
dimnames(X) <- list()



2.8.3 행렬의 행 또는 열 계산

모든 행 또는 모든 열을 갖고 있는 행렬의 일부를 선택하기 위해 첨자를 사용할 수 있습니다. 다음은 최우측 열(숫자 5)에 대한 평균이며, 전체 행에 대해서 연산 작업을 실행 합니다. 다음은 최우측 열 (숫자 5)에 대한 평균이며, 전체 행에 대해서 연산 작업을 실행 합니다. 다음 코드를 보면 공백 다음에 쉼표가 있을을 알아야 합니다.

# 5 번째 열에 대한 평균계산
mean(X[,5])
## [1] 1.25

또는 최하위 행의 모든 열에 대한 분산을 계산할 수 있다. 두 번째 위치에 공백이 있습니다.

var(X[4,])
## [1] 5.7

행렬에 대한 요약통계를 계산하기 위한 몇 개의 특정 함수는 다음과 같습니다.

rowSums(X)
## [1]  9  8  7 11
colSums(X)
## [1]  2 11 11  6  5
rowMeans(X)
## [1] 1.8 1.6 1.4 2.2
colMeans(X)
## [1] 0.50 2.75 2.75 1.50 1.25

이 함수들은 빠른 실행 속도를 위해 개발 되었습니다. NA 또는 NaN을 처리하는 미묘한 차이의 일부를 구별하기 힘들게 합니다. 이러한 미묘한 차이가 문제가 된다면, apply를 대산 적용합니다. apply의 margin의 설정값이 2이면 열이고, 1이면 행을 의미 한다는 것에 주의 해야 합니다.

apply(X,2, mean)
## [1] 0.50 2.75 2.75 1.50 1.25

열 내부에 있는 여러 행에 대한 더하기 연산을 하려고 할 수 도 있습니다. rowsum 함수는 이러한 기능을 실행하는 효율적인 함수이며 rowsum 함수는 rowSums와는 달리 단일 함수이고 모두 소문자입니다. 이 예제에서는 1행과 4행을 그룹 A로, 2행과 3행을 그룹 B로 그룹화 한다고 합시다. 그룹화 벡터는 행의 수와 동일한 길이를 갖고 있다는 점에 주의 해야 합니다.

group=c("A", "B", "B", "A")
rowsum(X, group)
##   [,1] [,2] [,3] [,4] [,5]
## A    1    5    8    3    3
## B    1    6    3    3    2

다음과 같이 tapply 또는 aggregate로 동일한 결과를 얻을 수 있지만, 처리 속도는 약간 느립니다.

tapply(X, list(group[row(X)], col(X)), sum)
##   1 2 3 4 5
## A 1 5 8 3 3
## B 1 6 3 3 2

tapply 에서 row(x)와 col(x)를 사용했으므로, group의 첨자로 row(x)를 설정 했습니다.

aggregate(X, list(group), sum)
##   Group.1 V1 V2 V3 V4 V5
## 1       A  1  5  8  3  3
## 2       B  1  6  3  3  2

행렬의 각 열의 요소를 독립적으로 섞는 다고 가장 합니다. 다음과 같이 각 열(margin 값 2이다.)에 sample 함수를 적용할 수 있으며 필요한 만큼의 섞인 샘플을 만들 수 있습니다.

apply(X, 2, sample)
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    4    1    0    2
## [2,]    0    1    2    2    1
## [3,]    0    2    2    1    1
## [4,]    1    4    6    3    1
apply(X,2, sample)
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    1    1    3    1
## [2,]    0    4    2    1    2
## [3,]    1    2    2    2    1
## [4,]    0    4    6    0    1

2.8.4 행렬에 행과 열 추가

특정한 경우에 행렬 아래에 한 행을 추가해 평균을 보여주고 오른쪽에 열을 추가하여 행의 분산을 계산 합니다.

X<-rbind(X,apply(X,2,mean))
X<-cbind(X,apply(X,1,var))
X
##      [,1] [,2] [,3] [,4] [,5]    [,6]
## [1,]  1.0 4.00 2.00  0.0 2.00 2.20000
## [2,]  0.0 4.00 2.00  1.0 1.00 2.30000
## [3,]  1.0 2.00 1.00  2.0 1.00 0.30000
## [4,]  0.0 1.00 6.00  3.0 1.00 5.70000
## [5,]  0.5 2.75 2.75  1.5 1.25 0.96875

소수 자릿수 1열과 2열에서는 1개, 3열과 4열에서는 2개 5열에서는 0개(정수)이며 6열에서는 5개로, 열에 따라 다른 점에 주의 하십시오. R의 기본 설정값은 전체 열의 소수점 중에서 최소개수를 기준으로 출력 합니다. 다음으로 여섯번째 열을 분산(variance)으로 다섯번째 행 평균(mean)으로 표시한다.

colnames(X)<-c(1:5, "variance")
rownames(X)<-c(1:4, "mean") 
X
##        1    2    3   4    5 variance
## 1    1.0 4.00 2.00 0.0 2.00  2.20000
## 2    0.0 4.00 2.00 1.0 1.00  2.30000
## 3    1.0 2.00 1.00 2.0 1.00  0.30000
## 4    0.0 1.00 6.00 3.0 1.00  5.70000
## mean 0.5 2.75 2.75 1.5 1.25  0.96875

2.8.5 sweep 함수

sweep 함수는 벡터, 행렬, 배열 데이터 프레임에서 배열 요약을 일괄차감 sweep out 하기 위해 사용한다. 데이터를 대상으로 개별 열 평균에서 벗어난 정도를 행렬로 표현합니다.

matdata <- read.table("https://drive.google.com/u/0/uc?id=1amZ1xnQ6Ts37DpRwGHzK7dL0z_4mjNl_&export=download") 

우선 행렬에서 일괄차감하려는 인자를 포함한 벡터를 만듭니다. 예제에서는 matdata에 대한 4개 열 평균을 계산하여 cols에 할당 한다.

(cols<-apply(matdata, 2, mean))
##     V1     V2     V3     V4 
##   4.60  13.30   0.44 151.60

sweep 함수에서 matdata 데이터를 대상으로 margin을 2로 설정한 다음 cols를 사용하면 matdata의 모든 데이터에 대해 해당 열 평균에서 벗어난 정도를 간단히 계산 할 수 있습니다.

sweep(matdata,2,cols)
##      V1   V2    V3    V4
## 1  -1.6 -1.3 -0.04 -26.6
## 2   0.4 -1.3  0.26  14.4
## 3   2.4  1.7  0.36  22.4
## 4   2.4  0.7  0.26 -23.6
## 5   0.4  4.7 -0.14 -15.6
## 6   4.4 -0.3 -0.24   3.4
## 7   2.4  1.7  0.06 -36.6
## 8  -2.6 -0.3  0.06  17.4
## 9  -3.6 -3.3 -0.34  30.4
## 10 -4.6 -2.3 -0.24  14.4

이전 sweep 명령에서 두 번째 인자인 margin 값을 2로 설정하면 열 기준으로 sweep 함수를 실행 한다는 점에 유의 하십시오. 각 데이터에 대해 열 평균과의 차이를 계산하는 기능과 관련된 함수에는 scale이 있으며, 이 함수는 표준편차를 이용해 데이터를 정규화 합니다.

예제 1

2022년 1월 부터 5월까지의 부동산 실거래가 셋이 있다. 이건에 대해서, 지역별 월별 데이터 추이를 나타내고, 그것에 대한 지역별 월별, 거래 횟수 평균과 합계 분산을 구하여라.

  library(httr)
  library(readxl)

# 부동산 데이터 셋 가져오는 함수 만들기

real_estate_fun <- function() {

  # 2022년도 데이터 가져오기
    url <- "https://drive.google.com/u/0/uc?id=1JC6JPtA4nK5ZRyii64NDO98LyU38kL0R&export=download"
    GET(url, write_disk(tf <- tempfile(fileext = ".xlsx")))
    apt_2022 <- read_excel(tf, 1L)

    df <- rbind(apt_2022)

    return(df)
}

# 부동산 셋 데이터 가져오기
system.time(
 df <- real_estate_fun()
)
##  사용자  시스템 elapsed 
##   1.346   0.276   6.415

위와 같이 부동산 데이터 셋을 가져 온다음 strsplit를 활용 하여, 행정구역을 가져 옵니다.

# map 함수를 돌리기 위해 purrr을 사용한다. map 함수는 속도가 매우 빠르다.
  library(purrr)
  library(dplyr)
## 
## 다음의 패키지를 부착합니다: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
  library(stringr)
  library(tidyr)

# word를 나누는 함수를 구한다.  여기에서 strsplit 함수가 쓰인다.
  word_fun <- function(i){
   split <-  unlist(strsplit(df$시군구[i]," "))
   word <-   data.frame(
      행정구역 = split[1]
   )
   return(word)
  }

# 아파트 데이터 프레임의 갯수를 df로 한다.
  x <- 1:nrow(df)

# map 함수로 list를 구한다.
  system.time(
   mylist <- x %>%
                map(word_fun)
  )
##  사용자  시스템 elapsed 
##  11.815   0.000  11.815
# list 파일을 데이터 프레임으로 바꾼다.
   apt_split <- as.data.frame(do.call(rbind,mylist))

 df <- cbind(apt_split, df)

그리고, 월별 행정 구역별로 데이터를 행렬 표를 만들기 위한 데이터 프레임을 구성 합니다.

# 데이터 그룹와 월별 행정구열별 거래량
 mt <-df %>%
        group_by(행정구역, 계약년월) %>%
        summarise(거래량 = n())
## `summarise()` has grouped output by '행정구역'. You can override using the
## `.groups` argument.
mt <- mt %>%
      spread(key= 계약년월, value = "거래량")
mt
## # A tibble: 17 × 6
## # Groups:   행정구역 [17]
##    행정구역       `202201` `202202` `202203` `202204` `202205`
##    <chr>             <int>    <int>    <int>    <int>    <int>
##  1 강원도             1316     1670     1995     1764     1460
##  2 경기도             3570     3991     5993     4960     3768
##  3 경상남도           2812     3182     3603     3386     2380
##  4 경상북도           1941     1990     2398     2170     1757
##  5 광주광역시         1122     1125     1435     1510     1228
##  6 대구광역시          781      804      953      710      692
##  7 대전광역시          560      563      693      499      392
##  8 부산광역시         1330     1427     1914     1692     1493
##  9 서울특별시         1119      831     1462     1001     1096
## 10 세종특별자치시      174      216      243      194      166
## 11 울산광역시          771      736      893      995      754
## 12 인천광역시          791      893     1212     1023      877
## 13 전라남도           1157     1225     1500     1221     1100
## 14 전라북도           1564     1752     2381     1915     1541
## 15 제주특별자치도      231      242      249      189      183
## 16 충청남도           1825     1991     2415     2199     1800
## 17 충청북도           1312     1594     1875     1779     1540

그리고 아래와 같이 matrix 데이터를 구성 합니다.

# 매트릭스 데이터 셋으로 구성합니다.
MT <- as.matrix(mt[2:6])

# 데이터 행정구역을 rowname으로 구성 합니다.
rownames(MT) <- mt$행정구역
MT
##                202201 202202 202203 202204 202205
## 강원도           1316   1670   1995   1764   1460
## 경기도           3570   3991   5993   4960   3768
## 경상남도         2812   3182   3603   3386   2380
## 경상북도         1941   1990   2398   2170   1757
## 광주광역시       1122   1125   1435   1510   1228
## 대구광역시        781    804    953    710    692
## 대전광역시        560    563    693    499    392
## 부산광역시       1330   1427   1914   1692   1493
## 서울특별시       1119    831   1462   1001   1096
## 세종특별자치시    174    216    243    194    166
## 울산광역시        771    736    893    995    754
## 인천광역시        791    893   1212   1023    877
## 전라남도         1157   1225   1500   1221   1100
## 전라북도         1564   1752   2381   1915   1541
## 제주특별자치도    231    242    249    189    183
## 충청남도         1825   1991   2415   2199   1800
## 충청북도         1312   1594   1875   1779   1540

월별 총거래량을 구합니다.

# # 월별 총거래량 
colSums(MT)
## 202201 202202 202203 202204 202205 
##  22376  24232  31214  27207  22227

행정구역별 월단위 평균 거래량을 구합니다.

colMeans(MT)
##   202201   202202   202203   202204   202205 
## 1316.235 1425.412 1836.118 1600.412 1307.471

시도별 누적 거래량을 구합니다.

  rowSums(MT)
##         강원도         경기도       경상남도       경상북도     광주광역시 
##           8205          22282          15363          10256           6420 
##     대구광역시     대전광역시     부산광역시     서울특별시 세종특별자치시 
##           3940           2707           7856           5509            993 
##     울산광역시     인천광역시       전라남도       전라북도 제주특별자치도 
##           4149           4796           6203           9153           1094 
##       충청남도       충청북도 
##          10230           8100

시도별 평균 거래량을 구합니다.

 rowMeans(MT)
##         강원도         경기도       경상남도       경상북도     광주광역시 
##         1641.0         4456.4         3072.6         2051.2         1284.0 
##     대구광역시     대전광역시     부산광역시     서울특별시 세종특별자치시 
##          788.0          541.4         1571.2         1101.8          198.6 
##     울산광역시     인천광역시       전라남도       전라북도 제주특별자치도 
##          829.8          959.2         1240.6         1830.6          218.8 
##       충청남도       충청북도 
##         2046.0         1620.0

시도별 거래량 표준편차를 구합니다.

  apply(MT, 1, sd)
##         강원도         경기도       경상남도       경상북도     광주광역시 
##      264.42012     1011.30475      484.54081      243.32427      179.26098 
##     대구광역시     대전광역시     부산광역시     서울특별시 세종특별자치시 
##      103.47705      109.44542      233.01867      231.06644       31.47698 
##     울산광역시     인천광역시       전라남도       전라북도 제주특별자치도 
##      111.00315      163.86641      153.84505      343.21466       30.69528 
##       충청남도       충청북도 
##      260.74509      219.22933

댓글 없음:

댓글 쓰기

css cheat sheet 클래스 선택자, margin(마진), display , center 조정 간단한 구성 요소

 앞에서는 html의 간단한 sheet를 소개 하였습니다.   html은  주로 골격을 나타나는 것이라, 디자인을 하는데는 css로 하여야 합니다.  아래 코드와 같이 css 관련 하여 매우 간단하게 코딩 하겠습니다.  body 부분의 css 코딩  ...