[R] 문자열 / 날짜 데이터 처리 맛보기

DongGyu Jung·2021년 11월 21일
0

어떤 언어에서든 중요한 요소들이 있다...!!
당연히 중요한 건 엄청 많지만..
데이터를 입맛에 맞게 전처리할 때 필수적이라고 할 수 있는
정규표현식날짜 관련 함수를 이번에 알아보려 한다.

Let's 기릿!💨💨


🕐 날짜 함수 ( feat. "format"의 간보기)

# 대입 명령( <- )이더라도 양 끝에 ()를 감싸주면 바로 콘솔창에 출력된다.
#년-월-일 (시간X)
(today <- Sys.Date())

[1] "2021-11-16"

str(today)
Date[1:1], format: "2021-11-16"

class(today)
[1] "Date"

우선 Sys 라이브러리에 내장되어 있는 Date()라는 함수이다.
이 함수는 흔히 알고있는 os 모듈과 비슷한 성격의 라이브러리인 Sys 라이브러리에 속해있는데
현재 사용 중인 운영체제 기준 날짜를 표시해준다.

속성들을 살펴보면 str(Sys.Date())를 해보았을 때,
형식이 "2021-11-16"이라는 것을 알 수 있다.
하지만 우리는...!!
하이픈으로 구분된 날짜만 사용한다면 답답해 미칠 것 이다.
우리의 입맛대로 출력 형식을 바꿔보자!

format(today, "%y년 %m월 %d일")
format(today, "%Y년 %m월 %d일")
format(today, "%d일 %B %Y년")
format(today, "%B %b %m")
format(today, "%b %e, %Y")
format(today, "%m %d, %Y")

[1] "21년 11월 16일"
[1] "2021년 11월 16일"
[1] "16일 11월 2021년"
[1] "11월 11 11"
[1] "11 16, 2021"
[1] "11 16, 2021"

🧷날짜 및 시간 형식

형식 지정자형식
%m/%d/%Ymm/dd/yyyy02/21/2018
%m/%d/%ymm/dd/yy02/21/18
%d/%m/%Ydd/mm/yyyy21/02/2018
%d/%m/%ydd/mm/yy21/02/18
%d-%m-%Ydd-mm-yyyy21-02-2018
%d-%m-%ydd-mm-yy21-02-18
%m-%d-%Ymm-dd-yyyy02-21-2018
%m-%d-%ymm-dd-yy02-21-18
%f/%e/%Ym/d/yyyy2/21/2018
%e/%f/%Yd/m/yyyy21/2/2018
%B %e, %YMonth d, yyyyFebruary 21, 2018
%b %e, %YMth d, yyyyFeb 21, 2018
%b %d, %YMth d, yyyyFeb 21, 2018
%B %d, %YMonth d, yyyyFebruary 21, 2018
%Y-%m-%d %H:%M:%Syyyy-mm-dd hh:mm:ss2018-02-21 12:00:00
%H:%M:%Shh:mm:ss12:00:00
%Y-%m-%d %I:%M:%S %pyyyy-mm-dd HH:MM:SS tt2018-10-29 10:02:48 AM
%Y-%m-%d %I:%M:%S %pyyyy-mm-dd HH:MM:SS tt2018-10-29 07:30:20 PM

출처 : IBM_날짜 및 시간 형식

아마 날짜 형식에서 %d, %m, %y 같은 형식 지정은 많이들 아실거라고 생각합니다.
물론 이외의 다양한 형식들을 아시겠지만...
필자는 %B같은 형식이나 배치 위치에 따라 표현되는 방식이 다양하다.

format(today, "%y")#2자리 년도
format(today, "%Y")#4자리 년도

[1] "21"
[1] "2021"

format(today, "%B")#"월"자 
format(today, "%b")#숫자 개월수
format(today, "%m")#2자리 숫자 개월 수

[1] "11월"
[1] "11"
[1] "11"

format(today, "%a")
format(today, "%A")

[1] "화"
[1] "화요일"

여기까지
Date 데이터를 "인수"로 사용하는 날짜 관련 함수이다.
'요일'이나 '월', '분기'를 구하는 함수 등이 있다.

# format(today, "%A")
weekdays(today) 
[1] "화요일"

# format(today, "%B")
months(today) 
[1] "11월"

# 분기
quarters(today)
[1] "Q4"

# 1970-01-01을 기준으로 얼마나 날짜가 지났지는 지의 값을 가지고 있다.
unclass(today)
[1] 18947

#Date는 대문자(미국식 날짜및 시간 : date) time 소문자
Sys.Date()
[1] "2021-11-17"

Sys.time()
[1] "2021-11-17 00:33:58 KST"

#Date 형식 / POSIXct 형식 다름.
str(Sys.Date())
str(Sys.time())
Date[1:1], format: "2021-11-17"
POSIXct[1:1], format: "2021-11-17 00:35:41"

class(Sys.time())
[1] "POSIXct" "POSIXt"
[1] "Date"

#sys 날짜 데이터 지역
Sys.timezone()
[1] "Asia/Seoul"

이번엔 as.Date()라는 간편한 날짜 데이터 변환 함수를 알아보자!
기본형식은 하이픈("-")으로 구분한 형식으로 출력되지만
format='' 인수로 출력형식을 설정할 수 있다.

as.Date('1/15/2021') # 에러발생
Error in charToDate(x) : 문자열이 표준서식을 따르지 않습니다

as.Date('2021/1/15') # 잘 인식한다.
[1] "2021-01-15"

as.Date('1/15/2021',format='%m/%d/%Y') # format 은 생략 가능
as.Date('4월 26, 2018',format='%B %d, %Y')
[1] "2021-01-15"
[1] "2018-04-26"

as.Date('110228',format='%d%b%y') 
[1] NA

as.Date('110228',format='%y%m%d') 
as.Date('11228',format='%d%b%y') 
[1] "2011-02-28"
[1] "2028-02-11"

# 데이터 형식으로 변환된 것을 확인할 수 있음.
str(as.Date('11228',format='%d%b%y'))
Date[1:1], format: "2028-02-11"

밑에 보이는 strptime()as.Date()와 비슷한 함수이지만
Date와 다른 점은 Date객체가 아닌 POSIX 시간형인 점이고 초단위까지 표현된다.
함수명에서 보이는 ptime의 p는 POSIX형이기에..!!

x1 <- "2021-01-10 13:30:41"
# 문자열을 날짜형으로
d <- as.Date(x1, "%Y-%m-%d %H:%M:%S") 
d
[1] "2021-01-10"

class(d)
[1] "Date"

# 문자열을 날짜+시간형으로
# Format 형식은 %Y-%m-%d %H:%M:%S로 동일하지만 초단위까지 모두 출력됨.
t <- strptime(x1, "%Y-%m-%d %H:%M:%S")
t
[1] "2021-01-10 13:30:41 KST"

class(t)
[1] "POSIXlt" "POSIXt"

strptime('2021-08-21 14:10:30', "%Y-%m-%d %H:%M:%S")
[1] "2021-08-21 14:10:30 KST"

위에 설명한 것 처럼
as.Date()은 날짜 단위까지만 취급 가능하기 때문에 초가 다르더라도 차이가 없다고 출력한다
as.POSIXctas.POSIXlt는 초단위 연산이 가능하다.

그리고 추가적으로 설명을 해보자면 Date / Time 객체들은 차이(뺄셈) 연산 시,
"Time Difference of~~" 형태로 출력된다.

#POSIX : 초단위 시간 계산
as.Date("2021/01/01 08:00:00") - as.Date("2021/01/01 05:00:00")
as.POSIXct("2021/01/01 08:00:00") - as.POSIXct("2021/01/01 05:00:00")

> as.Date("2021/01/01 08:00:00") - as.Date("2021/01/01 05:00:00")
Time difference of 0 days
> as.POSIXct("2021/01/01 08:00:00") - as.POSIXct("2021/01/01 05:00:00")
Time difference of 3 hours

POSIXlt끼리의 연산과 POSIXct끼리의 연산 결과가 동일한 것을 볼 수 있다.

그렇다면 과연
"POSIXlt" 와 "POSIXct"의 차이점은 무엇일까?
unclass()를 통해 확인할 수 있다.

ct<-Sys.time()
lt<-as.POSIXlt(ct)
str(ct) 
str(lt) 

POSIXct[1:1], format: "2021-11-21 22:25:08"
POSIXlt[1:1], format: "2021-11-21 22:25:08"
 
 
>unclass(ct)
[1] 1637501108

>unclass(lt) 
$sec
[1] 8.123716

$min
[1] 25

$hour
[1] 22

$mday
[1] 21

$mon
[1] 10

$year
[1] 121

$wday
[1] 0

$yday
[1] 324

$isdst
[1] 0

$zone
[1] "KST"

$gmtoff
[1] 32400

attr(,"tzone")
[1] ""    "KST" "KDT"

<ct의 경우>
Epoch(1970년 1월 1일) 이후 경과된 시간(초)를 기준으로 날짜변환을 하고 메모리를 효율적으로 사용할 수 있다고 한다.

<lt의 경우>
복잡한 날짜 목록 구조로 구성되어 있지만
아래와 같이 각 목록 요소를 다양하게 활용할 수 있는 장점이 있다.

lt$mon+1
lt$hour
lt$year+1900

[1] 11
[1] 22
[1] 2021

#POSIXlt도 ct에 적용되는 초단위 형식의 데이터를 취급할 수 있긴하다.
as.POSIXct(1449894438,origin="1970-01-01")
as.POSIXlt(1449894438,origin="1970-01-01")
[1] "2015-12-12 13:27:18 KST"
[1] "2015-12-12 13:27:18 KST"

#이것이 목록형인 lt의 장점
#요일 (0 : 일요일 ~ 6: 토요일)
as.POSIXlt("2021/09/01")$wday
as.POSIXlt("2021/09/02")$wday
as.POSIXlt("2021/09/03")$wday
as.POSIXlt("2021/09/04")$wday
as.POSIXlt("2021/09/05")$wday
[1] 3
[1] 4
[1] 5
[1] 6
[1] 0

앞서 알아본 함수들과
한국어 요일을 출력하는 weekdays()함수를 활용해보자.

#내가 태어난 요일 출력하기
myday<-as.POSIXlt("1999-12-04")
weekdays(myday)
[1] "토요일"

#내가 태어난지 며칠
as.POSIXlt(Sys.Date()) - myday
Time difference of 8023.375 days

#올해의 크리스마스 요일 2가지방법
#weekdays => 요일명
#as.POSIXlt의 wday => 숫자
christmas2<-as.POSIXlt("2021-12-25")
weekdays(christmas2)
christmas2$wday

> weekdays(christmas2)
[1] "토요일"
> christmas2$wday
[1] 6

#2022년 1월 1일 어떤 요일
tmp<-as.POSIXct("2022-01-01")
weekdays(tmp)
[1] "토요일"

#오늘은 xxxx년x월xx일x요일입니다 형식으로 출력
tmp<-Sys.Date()
format(tmp,'오늘은 %Y년 %B %d일 %A입니다')
[1] "오늘은 2021년 11월 21일 일요일입니다"

year<-format(tmp,'%Y')
month<-format(tmp,'%m')
day<-format(tmp,'%d')
weekday<-format(tmp,'%A')
cat("오늘은 ",year,"년 ",month,"월 ",day,"일 ",weekday," 입니다.\n",sep="")
오늘은 20211121일 일요일 입니다.

날짜와 시간 관련된 기능은
여기 저기 여러 상황에서 필요한 기능이고
각 언어마다 정말 다양한 함수/모듈/라이브러리가 있다!!
위 내용은 새발의 피(?) 정도로 극히 일부분이기 때문에 앞으로도 더 다양한 방법들을 숙지해야할 듯 하다.

0개의 댓글