x==x; Useless Equation?
새책 소개 (R로 하는 빅데이터 분석)[1]
- 제목 : R로 하는 빅데이터 분석: 데이터 전처리와 시각화
- 출판사 : 숨은원리
- 지음 : 김권현
- 쪽수 : 328쪽
- 발행일 : 2019년 3월 1일
- ISBN : 979-11-960144-7-6(93000)
- 이 포스트의 주소 : http://141.164.34.82/?p=905
[1]: 이 포스트(post)는 2019년 2월 20일 발표 내용입니다.
지은이 소개
- 이름 : 김권현
- 서울대 인지과학 박사
- 서강대, 국민대, 명지대 등 출강
- 지난해
zeroone.ai
AI Research Lead - 전작
책을 쓰게 된 동기
우선 R의 복잡한 구문을 한번 살펴 봅시다. 예를 들어 데이터 프레임이라는 데이터 구조의 일부분을 참조하기 위한 방법은 df[1]
, df["colname"]
, df[["colname"]]
, df[[1]]
, df[1,2]
, df["rowname", "colname"]
, df$colname
, df[df$colname>1,]
등 굉장히 다양합니다. 그리고 동일한 방법이 다른 데이터 구조(행렬, 리스트 등)에도 사용될 수 있는 경우가 있는 반면, 사용할 수 없기도 합니다. 하지만 이를 구분하는 원리가 무엇일까요? 제가 R을 배울 때도 그렇고, 당시의 대부분의 책은 “이런 걸 하려면 이렇게 해” 또는 “이런 기능들이 있어”가 다였습니다. 경우에 따라 조금씩 달라지는 문법을 이해하지 못하면 그냥 외워야 하는데, 아무 생각없이 외우기에는 너무 분량이 많았죠. 그리고 핵심적인 원리를 이해하지 못하고 그때 그때 임시변통으로 프로그램을 짜게 되면 찾기도 힘든 논리적 오류(또는 버그)가 생기게 마련이고, 이런 버그가 생기면 부호 하나, 함수 하나 때문에 머리를 쥐어짜며 고생을 하게 됩니다.
주요 내용 소개
-
날짜와 시간
-
data.table
패키지 -
문자열
-
정규표현식
-
ggplot2
오늘의 주제?!
-
수학에서 가장 명백한 사실, \(x=x\)!
- 수학계의 “나는 생각한다. 고로 나는 존재한다!”
- 의심할 나위 없이 명백한 사실???
-
R에서도
x<-y; x==y
는 항상 참(TRUE
)일까?
x<-y; x==y
test = function(x) {
y <- x
return(x==y)
}
test(3)
test(NA)
test(NaN)
test(NULL)
## [1] TRUE ## [1] NA ## [1] NA ## logical(0)
NA
는 결측치를 의미하고, 마치 수학의 미지수 \(x\) 와 같다. NA==NA
가 NA
가 되는 상황은 마치 수학에서 명제 \(x=y\) 의 진위를 판정하는 것과 비슷한 듯 합니다. 반면 \(x \in A\) 를 의미하는 %in%
연산에서는 다르게 작동합니다! $x \in { x } $ 를 생각할 때, NA %in% NA
는 NA
를 수학에서 미지수 \(x\) 로 생각할 때, \(x \in {x}\) 와 비슷하게 작동하는 것이죠.
test = function(x) {
y <- x
return(x %in% y)
}
test(3)
test(NA)
test(NaN)
test(NULL)
## [1] TRUE ## [1] TRUE ## [1] TRUE ## logical(0)
다음의 결과를 보고 R이 왜 그렇게 작동하는지 생각해봅시다.
x= NA
x | TRUE
x & FALSE
x | !x
## [1] TRUE ## [1] FALSE ## [1] NA
다음은 수학적으로 옳은 결과일까요?
1/0
## [1] Inf
정규표현식의 기초
정규표현식을 문자열을 활용해 문자열의 패턴을 나타내기 때문에 문자 중의 일부를 패턴을 나타내기 위해 사용한다. 다음의 문자들은 정규표현식에서 문자 그대로의 문자를 의미하지 않는다.
. [ ] \ { } * + ? ^ $ ( ) |
여기서는 이들 문자를 문자 그대로의 문자로 사용하려면 어떻게 해야 하는지 알아봅시다.
- 가장 쉬운 방법은
fixed=TRUE
로 놓는 것입니다.
grepl(pattern='.', c('abc', 'ab.c'))
## [1] TRUE TRUE
- 하지만 정규표현식에서는 항상
grepl(x, x)
가TRUE
가 되지 않습니다. 왜냐하면 위에서 봤던 기호들 때문이지요.
사실 이 부분은 정규표현식을 실제로 사용할 때 가끔 부딪히게 되는 문제이고, 적절한 경험 없이 정규표현식을 사용하면 오류가 발생되기 쉽고, 그 오류를 찾아내기 위해 많은 시간을 허비해야 함에도 불구하고 정규표현식을 설명하는 많은 문서에서 누락하고 있는 부분이기도 합니다.
일단 실험을 해봅시다.
library(dplyr)
library(stringr)
symbols <- ".[]\\{}*+?^$()|"
for (i in 1:nchar(symbols)) {
x <- substr(symbols, i, i)
y <- x
tryCatch({
z <- grepl(x, x)
if (!z) {
cat(paste0("grepl(", x, ",", x, ") is FALSE!\n"))
}
}, warning = function(warning_condition) {
cat(paste0("grepl(", x, ",", x, ") produce WARNING!\n"))
#print(warning_condition); print(z1); print(z2)
#cat(i, "\n")
}, error = function(error_condition) {
cat(paste0("grepl(", x, ",", x, ") produce ERROR!\n"))
#print(error_condition); print(z1); print(z2)
#cat(i, "\n")
})}
## grepl([,[) produce ERROR! ## grepl(\,\) produce ERROR! ## grepl({,{) produce ERROR! ## grepl((,() produce ERROR!
어랏! 이 결과만 보면 단지 4개의 문자를 제외하고는 grepl(x,x)
이 TRUE
입니다! 하지만 TRUE
라고 문제가 없는 것은 아니다. 같은 것을 같다고 하는 것으로는 부족하다. (이건 일종의 확증편향일 수 있다.) 다른 것도 다르다고 해야 한다!
library(dplyr)
library(stringr)
symbols <- ".[]\\{}*+?^$()|"
for (i in 1:nchar(symbols)) {
x <- substr(symbols, i, i)
y <- "a"
tryCatch({
z <- grepl(x, y)
if (z) {
cat(paste0("grepl(", x, ",", y, ") is TRUE!\n"))
}
}, warning = function(warning_condition) {
cat(paste0("grepl(", x, ",", y, ") produce WARNING!\n"))
#print(warning_condition); print(z1); print(z2)
#cat(i, "\n")
}, error = function(error_condition) {
cat(paste0("grepl(", x, ",", y, ") produce ERROR!\n"))
#print(error_condition); print(z1); print(z2)
#cat(i, "\n")
})}
## grepl(.,a) is TRUE! ## grepl([,a) produce ERROR! ## grepl(\,a) produce ERROR! ## grepl({,a) produce ERROR! ## grepl(*,a) is TRUE! ## grepl(+,a) is TRUE! ## grepl(?,a) is TRUE! ## grepl(^,a) is TRUE! ## grepl($,a) is TRUE! ## grepl((,a) produce ERROR! ## grepl(|,a) is TRUE!
뭐 이런 것 까지 알 필요가 있을까 싶을 수도 있을 것입니다. 하지만 제 경험 상 오류를 방지하는데 도움이 됩니다.
예를 들어 숫자에 |
로 끝나는 패턴을 찾을 때, |
앞에 \
를 빼놓을 수 있습니다. 그렇게 하면 어떻게 될까요? 어쨋든 숫자가 들어간 패턴을 찾을 것이라고 안이하게 생각하면 안 됩니다.
grepl('\\d+|', c('2341|', '23411'))
## [1] TRUE TRUE
이것만 보면, “거봐, 숫자가 들어간 걸 찾잖아?"라고 말할지 모릅니다. 하지만 다음을 봅시다.
grepl('\\d+|', c('abc', '.+...'))
## [1] TRUE TRUE
또는 긴 정규표현식에서 )
를 하나쯤 더 집어넣는다면 어떻게 될까요? 앞의 (
와 쌍이 맞지 않는 )
는 에러가 날 거라고 안이하게 생각하면 안 됩니다.
grepl('(\\d+))', c('1234', '1234)'))
## [1] FALSE TRUE
이 결과를 보고 나니 과연 위에서 열거한 모든 기호에 대해 \
를 앞에 붙이면 문자 그대로 기호가 되는지에 대해 의구심이 생겼다. 뭐 해보는 수 밖에.
library(dplyr)
library(stringr)
symbols <- ".[]\\{}*+?^$()|"
for (i in 1:nchar(symbols)) {
x <- substr(symbols, i, i)
y <- paste0('\\', x)
tryCatch({
z1 <- grepl(y, x)
z2 <- grepl(y, 'a')
if (!z1) {
cat(paste0("grepl(", y, ",", x, ") is FALSE!\n"))
}
if (z2) {
cat(paste0("grepl(", y, ", a) is TRUE!\n"))
}
}, warning = function(warning_condition) {
cat(paste0("grepl(", y, ",", x, ") produce WARNING!\n"))
#print(warning_condition); print(z1); print(z2)
#cat(i, "\n")
}, error = function(error_condition) {
cat(paste0("grepl(", y, ",", x, ") produce ERROR!\n"))
#print(error_condition); print(z1); print(z2)
#cat(i, "\n")
})}
아무것도 나오지 않는 것보니 위에서 열거한 모든 기호에 대해 \
를 앞에 붙이면 문자 그대로의 의미를 뜻합니다.
그렇다면 [
, ]
안에서는 어떨까요?
ERE는 [
, ]
안에서 모든 문자가 문자 그대로의 문자를 의미합니다. 이것은 PCRE(Perl-Compatible Regular Expression)과의 큰 차이점이기도 하죠. 그래서 PCRE를 쓰면 [
,]
안에서도 \
를 나타내기 위해 \\\\
를 써야 합니다!!!
grepl("[\\a]", c("\\", "a", "b"))
## [1] TRUE TRUE FALSE
grepl("[\\a]", c("\\", "a", "b"), perl=TRUE)
## [1] FALSE FALSE FALSE
grepl("[\\\\a]", c("\\", "a", "b"), perl=TRUE)
## [1] TRUE TRUE FALSE
그렇다면 \(x \neq y\) 이면 x!=y
가 항상 성립할까요? 혹은 \(x \neq y\) 이면 항상 x!=y
가 되는 것이 좋은 것일까요?
다음의 텍스트를 봅시다. 합자(ligature; 리거쳐)[2]나 움라우트가 따로 혹은 합쳐 있는 문자의 경우(pdf에서 복사 붙여넣기하면 볼 수 있죠)에는 다른 걸 다르다고 하는 게 꼭 좋은 게 아니죠.
x <- c("He sni\ufb00ed.", "\u00fc")
y <- c("He sniffed.", "u\u0308")
x == y
## [1] FALSE FALSE
이럴 땐 어떻게 해야 할까요?
Leave a comment