지난번 포스팅에서는 Python standard datetimepandas Timestamp 객체로 날짜-시간 데이터를 입력, 변환, 조회하는 방법을 소개하였습니다. 


이번 포스팅에서는 


(1) Python datetime, pandas Timestamp 객체를 문자열(string)로 변환

    (Converting native Python datetime, pandas Timestamp objects to Strings)


(2) 문자열(string)을 Python datetime, pandas Timestamp 객체로 변환

    (Converting Strings to Python datetime, pandas Timestamp)


에 대해서 차례대로 알아보겠습니다. 





  (1) Python datetime, pandas Timestamp 객체를 문자열(string)로 변환

      (Converting native Python datetime, pandas Timestamp objects to Strings)



(1-1) str() 함수를 이용하여 Python datetime 객체를 문자열(string)로 변환하기



# Create Python datetime objects

import datetime as dt

ts = dt.datetime(2019, 12, 22, 13, 30, 59) # (year, month, day, hour, minume, second)

type(ts)

[Out]: datetime.datetime

 

ts

[Out]: datetime.datetime(2019, 12, 22, 13, 30, 59)



# converting Python datetime objects to Strings

ts_str = str(ts)

type(ts_str)

[Out]: str


ts_str

[Out]: '2019-12-22 13:30:59'


# indexing from a string

print('year-month-day:', ts_str[:10])

[Out]: year-month-day: 2019-12-22

print('hour:minute:second:', ts_str[10:])
[Out]: hour:minute:second:  13:30:59





(1-2) strftime() 메소드를 이용하여 Python datetime 객체를 문자열(string)로 변환하기


Python standard datetime 객체의 포맷에 맞추어서 strftime() 메소드의 괄호 안에 형태 지정(format specification)을 해줍니다. 가령 4자리 년(4-digit year), 월(month), 일(day), 0-23시간(0-23 hour), 분, 초의 형태로 지정을 하고 싶으면 strftime('%Y-%m-%d %H:%M:%S') 로 설정을 해주면 됩니다. 



import datetime as dt


ts = dt.datetime(2019, 12, 22, 13, 30, 59) # (year, month, day, hour, minume, second)

ts

[Out]: datetime.datetime(2019, 12, 22, 13, 30, 59)


ts_strftime = ts.strftime('%Y-%m-%d %H:%M:%S')

type(ts_strftime)

[Out]: str


ts_strftime

[Out]: '2019-12-22 13:30:59'




년도를 '2자리 연도(2-digit year)'로 문자열 변환하고자 하면 '%y' 를 사용하며, 0-11시간(0-11 hour) 형태로 시간을 문자열 변환하고자 하면 '%I'를 사용합니다. 



# %Y: 4-digit year vs. %y: 2-digit year

# %H: 24-hour clock[00, 23] vs. %I: 12-hour clock [01, 11]

ts.strftime('%y-%m-%d %I:%M:%S')

[Out]: '19-12-22 01:30:59'

 



datetime.datetime(2019, 12, 22).strftime('%w') 는 주 단위의 요일을 일요일은 '0', 월요일은 '1', ..., 토요일은 '6'으로 순서대로 정수의 문자로 반환합니다. 



# '%w': weekday

print('----- %w: weekday as integer -----')

print('Sunday    :', dt.datetime(2019, 12, 22).strftime('%w'))

print('Monday    :', dt.datetime(2019, 12, 23).strftime('%w'))

print('Tuesday   :', dt.datetime(2019, 12, 24).strftime('%w'))

print('Wednesday :', dt.datetime(2019, 12, 25).strftime('%w'))

print('Thursday  :', dt.datetime(2019, 12, 26).strftime('%w'))

print('Friday    :', dt.datetime(2019, 12, 27).strftime('%w'))

print('Saturday  :', dt.datetime(2019, 12, 28).strftime('%w'))


[Out]: 
----- %w: weekday as integer -----
Sunday    : 0
Monday    : 1
Tuesday   : 2
Wednesday : 3
Thursday  : 4
Friday    : 5
Saturday  : 6



datetime.datetime(2019, 12, 22).strftime('%U')는 년 중 해당 주의 숫자(week nuber of the year)를 반환합니다. 이때 '%U'는 일요일이 주의 첫번째 일로 간주하는 반면에 '%W'는 월요일을 주의 첫번째 일로 간주하는 차이가 있습니다. 



# '%U': week number of the year [00, 53]. 

# Sunday is considered the first day of the week

dt.datetime(2019, 12, 22).strftime('%U') # '2019-12-22' is Sunday

[Out]: '51'

 




# '%W': week number of the year [00, 53]. 

# Monday is considered the first day of the week

dt.datetime(2019, 12, 22).strftime('%W') # '2019-12-22' is Sunday

[Out]: '50'

 

dt.datetime(2019, 12, 23).strftime('%W') # '2019-12-23' is Monday

[Out]: '51'





(1-3) pandas Timestamp를  strftime() 메소드를 사용하여 문자열(string)로 변환하기



import pandas as pd


pd_ts = pd.Timestamp(2019, 12, 22, 13, 30, 59)

pd_ts

[Out]: Timestamp('2019-12-22 13:30:59')


# convert pandas Timestamp to string

pd_ts.strftime('%y-%m-%d %I:%M:%S')

[Out]: '19-12-22 01:30:59'

 





  (2) 문자열(string)을 Python datetime, pandas Timestamp 객체로 변환

       (Converting Strings to Python datetime, pandas Timestamp)



(2-1) datetime.strptime() 함수를 이용하여 문자열을 Python datetime.datetime 객체로 변환하기


strptime(문자열, 날짜-시간 포맷) 의 괄호 안에는 문자열의 형태에 맞추어서 반환하고자 하는 날짜-시간 포맷을 설정해줍니다. 



# create a string with 'year-month-day hour:minute:second'

ts_str = '2019-12-22 13:30:59'

ts_str

[Out]: '2019-12-22 13:30:59'


# convert a string to datetime object

import datetime as dt

dt.datetime.strptime(ts_str, '%Y-%m-%d %H:%M:%S')

[Out]: datetime.datetime(2019, 12, 22, 13, 30, 59)

 



여러개의 날짜-시간 문자열로 구성된 리스트를 List Comprehension 을 이용해서 datetime 객체 리스트로 만들 수 있습니다. 



# convert strings list using list comprehension

ts_str_list = ['2019-12-22', '2019-12-23', '2019-12-24', '2019-12-25']


[dt.datetime.strptime(date, '%Y-%m-%d') for date in ts_str_list]

[Out]: 
[datetime.datetime(2019, 12, 22, 0, 0),
 datetime.datetime(2019, 12, 23, 0, 0),
 datetime.datetime(2019, 12, 24, 0, 0),
 datetime.datetime(2019, 12, 25, 0, 0)]




아래의 예는 pandas DataFrame에서 "Date" 문자열 칼럼과 "Time" 문자열 칼럼이 분리되어 있는 경우, (1) 먼저 이 두 칼럼을 "DateTime" 이라는 하나의 칼럼으로 합치고, (2) 그 다음에 문자열(Strings)을 DateTime 객체로 변환하는 방법에 대한 소개입니다. 


apply() 함수 안에 strptime() 함수를 lambda 무기명 함수 형태로 사용하였으며, 날짜와 시간 포맷도 위와는 조금 다르게 설정해보았습니다. ('%d/%m/%Y %H.%M.%S'))



import pandas as pd


# make a sample DataFrame with Date and Time (string format)

Date = ['01/12/2019', '01/12/2019', '01/12/2019']

Time = ['09.01.00', '09.01.01', '09.01.02']

val = [1, 2, 3]


df = pd.DataFrame({'Date': Date,

                   'Time': Time,

                   'val': val})


df

[Out]:

DateTimeval
001/12/201909.01.001
101/12/201909.01.012
201/12/201909.01.023

# combine 'Date' and 'Time' column as 'DateTime'

df['DateTime'] = df.Date + ' ' + df.Time

df

[Out]:

DateTimevalDateTime
001/12/201909.01.00101/12/2019 09.01.00
101/12/201909.01.01201/12/2019 09.01.01
201/12/201909.01.02301/12/2019 09.01.02


# check date type : strings

type(df.DateTime[0])

[Out]: str


# convert 'DateTime' column from strings to datetime object 

# using datetime.strptime() and lambda, apply function

from datetime import datetime


df.DateTime = df.DateTime.apply(lambda x: datetime.strptime(x, '%d/%m/%Y %H.%M.%S'))

df.set_index('DateTime', inplace=True)

df

[Out]:

DateTimeval
DateTime
2019-12-01 09:01:0001/12/201909.01.001
2019-12-01 09:01:0101/12/201909.01.012
2019-12-01 09:01:0201/12/201909.01.023


# check data type : datetime object Timestamp

type(df.index[0])

[Out]: pandas._libs.tslibs.timestamps.Timestamp




datetime.strptime(문자열, 날짜-시간 포맷) 의 경우 날짜-시간 문자열의 형태가 제한적이어서 아래와 같은 순서/형태의 문자열일 경우 ValueError 가 발생합니다. 이럴 경우 (2-2) dateutil.parser 의 parse() 함수를 사용하여 유연하게 날짜-시간 문자열을 파싱할 수 있습니다. 



dt.datetime.strptime('Dec 22, 2019 13:30:59', '%m %d, %Y %H:%M:%S')

[Out]: 
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-42-7dfd356853ba> in <module>
----> 1 dt.datetime.strptime('Dec 22, 2019 13:30:59', '%m %d, %Y %H:%M:%S')

~/anaconda3/envs/py3.6_tf2.0/lib/python3.6/_strptime.py in _strptime_datetime(cls, data_string, format)
    563     """Return a class cls instance based on the input string and the
    564     format string."""
--> 565     tt, fraction = _strptime(data_string, format)
    566     tzname, gmtoff = tt[-2:]
    567     args = tt[:6] + (fraction,)

~/anaconda3/envs/py3.6_tf2.0/lib/python3.6/_strptime.py in _strptime(data_string, format)
    360     if not found:
    361         raise ValueError("time data %r does not match format %r" %
--> 362                          (data_string, format))
    363     if len(data_string) != found.end():
    364         raise ValueError("unconverted data remains: %s" %

ValueError: time data 'Dec 22, 2019 13:30:59' does not match format '%m %d, %Y %H:%M:%S'




(2-2) dateutil 라이브러리의 parser.parse() 함수를 이용하여 문자열을 datetime 객체로 변환하기


아래의 3개의 예에서 보는 바와 같이, dateutil 라이브러리의 parser.parse() 함수는 괄호 안에 다양한 형태의 날짜-시간 문자열을 유연하게 인식하여 datetime.datetime 객체로 반환해줍니다. (2-1)의 datetime.strptime() 함수와 비교했을 때 dateutil.parser의 parse() 함수는 상대적으로 편리하고 강력합니다. 



# Converting Strings to datetime.datetime objects using parser.parse()

from dateutil.parser import parse


parse('2019-12-22 13:30:59')

[Out]: datetime.datetime(2019, 12, 22, 13, 30, 59)


parse('Dec 22, 2019 13:30:59')

[Out]: datetime.datetime(2019, 12, 22, 13, 30, 59)


parse('Dec 22, 2019 01:30:59 PM')

[Out]: datetime.datetime(2019, 12, 22, 13, 30, 59)




parse() 함수의 괄호 안 문자열의 첫번째 숫자가 '월(month)' 인지 아니면 '일(day)' 인지를 dayfirst=False (default), dayfirst=True 옵션을 사용하여 명시적으로 지정해줄 수 있습니다. 



# month first

parse('01/12/2019 13:30:59')

[Out]: datetime.datetime(2019, 1, 12, 13, 30, 59)


# day first

parse('01/12/2019 13:30:59', dayfirst=True)

[Out]: datetime.datetime(2019, 12, 1, 13, 30, 59)




여러개의 날짜-시간 문자열로 구성된 리스트를 가지고 List Comprehension을 사용하여 datetime.datetime 객체 리스트를 생성할 수 있습니다. 



# convert strings list using list comprehension

ts_str_list = ['2019-12-22', '2019-12-23', '2019-12-24', '2019-12-25']

[parse(date) for date in ts_str_list]

[Out]: 
[datetime.datetime(2019, 12, 22, 0, 0),
 datetime.datetime(2019, 12, 23, 0, 0),
 datetime.datetime(2019, 12, 24, 0, 0),
 datetime.datetime(2019, 12, 25, 0, 0)]

 




(3-3) pandas 의 pd.to_datetime()으로 날짜-시간 문자열을 pandas Timestamp 로 변환하기


* pandas Timestamp 에 대한 자세한 설명은 https://rfriend.tistory.com/497 참조하세요



# pandas Timestamp

import pandas as pd


pd.to_datetime('2019-12-22 13:30:59')

[Out]: Timestamp('2019-12-22 13:30:59')




여러개의 날짜-시간 문자열로 구성된 문자열 리스트를 가지고 pandas.to_datetime() 함수를 사용하여 pandas DatetimeIndex 를 생성할 수 있습니다. 이렇게 생성된 DatatimeIndex는 시계열 데이터로 이루어진 pandas Series나 pandas DataFrame 를 생성할 때 index로 사용할 수 있습니다. 



# pandas DatetimeIndex

ts_str_list = ['2019-12-22', '2019-12-23', '2019-12-24', '2019-12-25']

pd.to_datetime(ts_str_list)

DatetimeIndex(['2019-12-22', '2019-12-23', '2019-12-24', '2019-12-25'], dtype='datetime64[ns]', freq=None)



많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)


Posted by R Friend R_Friend

댓글을 달아 주세요

 

R 데이터 객체를 신규로 생성했거나, 외부에서 불러왔거나, 아니면 R 패키지에 내장되어 있는 데이터 셋을 활용한다고 했을 때 데이터 객체의 현황, 특성에 대해서 파악하는 것이 필요합니다.

 

이에 유용한 함수들을 알아보도록 하겠습니다.

 

 

 R 데이터 객체 탐색을 위한 함수 

 

R에 기본으로 내장되어 있는 'mtcars' 라는 데이터 프레임을 가지고 아래의 각 함수들의 예시를 들어보겠습니다.

'mtcars' 데이터는 1974 Motor Trend US magazine에서 자동차 디자인과 성능에 관해 추출한 11개의 변수로 구성된 데이터 프레임입니다.

 

> mtcars
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2 

 

'mrcars' 라고 콘솔창에 치면 위의 박스 상자에 있는 것처럼 데이터 보기가 가능합니다. 이처럼 데이터 관찰치와 변수가 몇 개 안되면 콘솔창이나 아니면 environment 창에서 데이터셋을 눌러서 미리보기를 할 수 있겠읍니다만, 데이터 관찰치가 몇 백만이 되고 변수도 수천개가 넘는 데이터 객체라면 무리겠지요. 그래서 아래 함수들이 필요합니다.

 

 

(1) str(객체) : 데이터 구조, 변수 개수, 변수 명, 관찰치 개수, 관찰치의 미리보기

 

> str(mtcars)
'data.frame':	32 obs. of  11 variables:
 $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
 $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
 $ disp: num  160 160 108 258 360 ...
 $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
 $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
 $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
 $ qsec: num  16.5 17 18.6 19.4 17 ...
 $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
 $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
 $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
 $ carb: num  4 4 1 1 2 1 4 2 2 4 ... 

 

mtcars 가 '32개의 관측치', '11개의 변수'로 되어있는 '데이터 프레임'이고, 각 변수명과 변수들의 유형, 그리고 상위 10개의 관측치가 미리보기 형식으로 제시됩니다. 데이터 셋 탐색을 위해 제일 처음 해보면 좋을 유용한 함수입니다.

 

 

(2) head(), tail() : 상위 6개, 하위 6개 관측치 미리보기

 

> head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1


>
tail(mtcars) mpg cyl disp hp drat wt qsec vs am gear carb Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.7 0 1 5 2 Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.9 1 1 5 2 Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.5 0 1 5 4 Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.5 0 1 5 6 Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.6 0 1 5 8 Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.6 1 1 4 2 

 

관측치가 수백만, 수천만 건인 경우는 상위 혹은 하위 몇개만 미리보기를 할 수 있으면 유용하겠지요.

 

 

(3) dim() : 데이터 객체의 차원

 

> dim(mtcars)
[1] 32 11 

 

str() 함수로 파악이 전부 가능한 정보인데요, 데이터 객체의 차원만 알고 싶거나 아니면 데이터 객체의 차원을 벡터로 해서 indexing해서 쓸일이 있을 때 이 함수를 사용하면 되겠지요.

 

 

(4) length() : 데이터 객체의 요소들의 개수

 

> length(mtcars) [1] 11

 

> length(mtcars$mpg)
[1] 32

 

첫번째 length(mtcars) 는 mtcars 데이터셋의 변수들의 개수를,

두번째 lenght(mtcars$mpg)는 mtcars의 데이터셋의 mpg라는 변수의 관측치의 개수를 나타냅니다.

(length()를 벡터에 사용하면 관측치의 개수를 나타냄)

목적에 맞게 골라서 사용하면 되겠습니다.

 

 

(5) names() : 데이터 객체 구성요소 이름

 

> names(mtcars)
 [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear" "carb"

 

데이터 객체의 변수명을 알고 싶고, indexing해서 사용하고 싶으면 names() 함수를 사용하면 되겠습니다.

 

 

(6) class() : 데이터 객체 구성요소의 속성

 

> class(mtcars)
[1] "data.frame"
> sapply(mtcars, class)
      mpg       cyl      disp        hp      drat        wt      qsec        vs        am 
"numeric" "numeric" "numeric" "numeric" "numeric" "numeric" "numeric" "numeric" "numeric" 
     gear      carb 
"numeric" "numeric" 

 

첫번째의 class(mtcars)는 데이터 객체가 '데이터 프레임'임을 나타내고 있으며,

두번째 sapply(mtcars, class)는 'mtcars'라는 데이터 프레임의 모든 변수에다가 'class()라는 함수를 적용해라(sapply)고 했을 때의 결과로서, 11개의 각 변수별로 속성을 나타내고 있습니다.

(참고로, sapply()는 동일한 함수를 모두 적용하라는 함수입니다. 여기서는 class()라는 함수를 mtcars 내의 모든 변수에 공통으로 적용하라는 뜻입니다)

이 또한 목적에 맞게 골라서 사용하면 되겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡' 단추를 꾸욱 눌러주세요.^^

 

Posted by R Friend R_Friend

댓글을 달아 주세요