예전 포스팅(https://rfriend.tistory.com/250)에서 pandas read_csv() 함수로 text, csv 파일을 읽어오는 방법을 소개하였습니다. 


이번 포스팅에서는 Python pandas의 read_csv() 함수를 사용하여 csv file, text file 을 읽어와 DataFrame을 만들 때 날짜/시간 (Date/Time) 이 포함되어 있을 경우 이를 날짜/시간 형태(DateTime format)에 맞도록 파싱하여 읽어오는 방법을 소개하겠습니다. 


[예제 샘플 데이터] 

date_sample






  (1) 날짜/시간 포맷 지정 없이 pd.read_csv() 로 날짜/시간 데이터 읽어올 경우


예제로 사용할 데이터는 위의 이미지 우측 상단에 있는 바와 같이 '1/5/2020 10:00:00' (1일/ 5월/ 2020년 10시:00분:00초) 형태의 날짜/시간 칼럼을 포함하고 있는 텍스트 파일입니다. 


이 예제 데이터를 날짜/시간 포맷에 대한 명시적인 설정없이 그냥 pandas의 read_csv() 함수로 읽어와서 DataFrame을 만들 경우 아래와 같이 object 데이터 형태로 불어오게 됩니다. 이럴 경우 별도로 문자열을 DateTime foramt으로 변환을 해주어야 하는 불편함이 있습니다. (참고: https://rfriend.tistory.com/498)



import pandas as pd


df = pd.read_csv('date_sample', sep=",", names=['date', 'id', 'val']) # no datetime parsing


df

dateidval
01/5/2020 10:00:00110
11/5/2020 10:10:00112
21/5/2020 10:20:00117
31/5/2020 10:00:00211
41/5/2020 10:10:00214
51/5/2020 10:20:00216


df.info()

<class 'pandas.core.frame.DataFrame'> RangeIndex: 6 entries, 0 to 5 Data columns (total 3 columns): date 6 non-null object <-- not datetime format id 6 non-null int64 val 6 non-null int64 dtypes: int64(2), object(1) memory usage: 272.0+ bytes




-- 날짜/시간 파싱 자동 추정 --

  (2) parse_dates=['date'] 칼럼에 대해 

      dayfirst=True 일이 월보다 먼저 위치하는 것으로 

      infer_datetime_format=True 날짜시간 포맷 추정해서 파싱하기


이번 예제 데이터의 경우 '1/5/2020 10:00:00' (1일/ 5월/ 2020년 10시:00분:00초) 처럼 '일(day)'이 '월(month)' 보다 먼저 나오으므로 dayfirst=True 로 설정해주었습니다. infer_datetime_format=True 로 설정해주면 Python pandas가 똑똑하게도 알아서 날짜/시간 포맷을 추정해서 잘 파싱해줍니다. 




df_date.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 3 columns):
date    6 non-null datetime64[ns] <-- datetime foramt!!
id      6 non-null int64
val     6 non-null int64
dtypes: datetime64[ns](1), int64(2)
memory usage: 272.0 bytes



import pandas as pd


df_date = pd.read_csv("date_sample", 

                      sep=",", 

                      names=['date', 'id', 'val'], 

                      parse_dates=['date']

                      dayfirst=True, # May 1st

                      infer_datetime_format=True)



df_date  # May 1st, 2020

dateidval
02020-05-01 10:00:00110
12020-05-01 10:10:00112
22020-05-01 10:20:00117
32020-05-01 10:00:00211
42020-05-01 10:10:00214
52020-05-01 10:20:00216




  (3) dayfirst=False 일(day)이 월(month)보다 뒤에 있는 파일 날짜/시간 파싱하기


만약에 '1/5/2020 10:00:00' (1월/ 5일/ 2020년 10시:00분:00초) 의 형태로 월(month)이 일(day)보다 먼저 나오는 파일을 읽어와서 파싱하는 경우에는 dayfirst=False 로 설정해주면 됩니다. (default 값은 False 이므로 생략 가능합니다)



df_date_dayfirstF = pd.read_csv("date_sample", 

                                sep=",", 

                                names=['date', 'id', 'val'], 

                                parse_dates=['date']

                                dayfirst=False, # January 5th, default setting

                                infer_datetime_format=True)



df_date_dayfirstF  # January 5th, 2020

dateidval
02020-01-05 10:00:00110
12020-01-05 10:10:00112
22020-01-05 10:20:00117
32020-01-05 10:00:00211
42020-01-05 10:10:00214
52020-01-05 10:20:00216

 




-- 날짜/시간 파싱 함수 수동 지정 --

  (4) date_parser=Parser 함수를 사용해서 데이터 읽어올 때 날짜/시간 파싱하기


위의 (2)번, (3)번에서는 infer_datetime_format=True 로 설정해줘서 pandas가 알아서 날짜/시간 포맷을 추정(infer)해서 파싱을 해주었다면요, 


이번에는 날짜/시간 파싱하는 포맷을 lambda 함수로 직접 명시적으로 사용자가 지정을 해주어서 read_csv() 함수로 파일을 읽어올 때 이 함수를 사용하여 날짜/시간 포맷을 파싱하는 방법입니다. 

이번 예제의 날짜/시간 포맷에 맞추어서 datetime.strptime(x, "%d/%m/%Y %H:%M:%S") 로 string을 datetime으로 변환해주도록 하였습니다. 



# parsing datetime string using lambda Function at date_parser

# Reference: converting string to DataTime: https://rfriend.tistory.com/498

import pandas as pd

from datetime import datetime


dt_parser = lambda x: datetime.strptime(x, "%d/%m/%Y %H:%M:%S")


df_date2 = pd.read_csv("date_sample", 

                       sep=",", 

                       names=['date', 'id', 'val'], 

                       parse_dates=['date'], # column name

                       date_parser=dt_parser)


df_date2

dateidval
02020-05-01 10:00:00110
12020-05-01 10:10:00112
22020-05-01 10:20:00117
32020-05-01 10:00:00211
42020-05-01 10:10:00214
52020-05-01 10:20:00216




참고로, pd.read_csv() 함수에서 날짜/시간 데이터는 위에서 처럼 parse_dates=['date'] 처럼 명시적으로 칼럼 이름을 설정해줘도 되구요, 아래처럼 parse_dates=[0] 처럼 위치 index 를 써주어도 됩니다. 



# parse_dates=[column_position]

import pandas as pd

from datetime import datetime


dt_parser = lambda x: datetime.strptime(x, "%d/%m/%Y %H:%M:%S")

df_date3 = pd.read_csv("date_sample", 

                       sep=",", 

                       names=['date', 'id', 'val'], 

                       parse_dates=[0], # position index

                       date_parser=dt_parser)


df_date3

dateidval
02020-05-01 10:00:00110
12020-05-01 10:10:00112
22020-05-01 10:20:00117
32020-05-01 10:00:00211
42020-05-01 10:10:00214
52020-05-01 10:20:00216





  (5) index_col 로 날짜-시간 데이터를 DataFrame index로 불러오기


마지막으로, 파일을 읽어올 때 index_col=['column_name'] 또는 index_col=column_position 을 설정해주면 날짜/시간을 pandas DataFrame의 index로 바로 읽어올 수 있습니다. 

(그냥 칼럼으로 읽어온 후에 date 칼럼을 reindex() 를 사용해서 index로 설정해도 됩니다. 

 * 참고: https://rfriend.tistory.com/255)



# use datetime as an index

import pandas as pd


df_date_idx = pd.read_csv("date_sample", 

                          sep=",", 

                          names=['date', 'id', 'val'], 

                          index_col=['date'], # or index_col=0 

                          parse_dates=True, 

                          dayfirst=True,

                          infer_datetime_format=True)



df_date_idx

idval
date
2020-05-01 10:00:00110
2020-05-01 10:10:00112
2020-05-01 10:20:00117
2020-05-01 10:00:00211
2020-05-01 10:10:00214
2020-05-01 10:20:00216




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

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


반응형
Posted by Rfriend

댓글을 달아 주세요

  1. 김광진 2020.06.01 18:35  댓글주소  수정/삭제  댓글쓰기

    R 데이터 분석 배운지는 얼마 안되었습니다..
    구글링 해가며 간단한 데이터 분석하는데 재미있더라구요..
    궁굼한게 있어서 구글링 하다가 질문을 하게 되었습니다..

    options(max.print = .Machine$integer.max)
    pool <- c(1:10000)
    test <- sample(pool,10000,replace = FALSE)
    sink("exe.txt")
    test
    sink()

    이렇게 하면 1에서 10000까지의 숫자가 랜덤하게 표현 되더라구요
    그런데
    ex) 1000 , 120, 3789, 4457, 7764, 23 이런 순서로 출력 될때까지 돌리고 만약 순서와 톡같은 배열이 나왔다면(처음부터 나오든, 중간부분이 똑같던 마지막 부분이 똑 같던 상관없이) ok.txt 로 저장을 하고 싶습니다...

    • Rfriend 2020.06.01 19:26 신고  댓글주소  수정/삭제

      안녕하세요 김광진님, 반갑습니다.
      아래 코드 참고하시기 바랍니다.
      (댓글란에 코드를 옮기면 들여쓰기가 없어져버리므로 RStudio에서 다시 정리해서 쓰시기 바랍니다)

      그리고 R과 Python으로 블로그 카테고리가 구분되어있습니다. R 코드 문의를 Python 카테고리의 글에 달아주셨습니다. ^^;

      options(max.print = .Machine$integer.max)
      pool <- c(1:10)
      N = 10
      search_seq <- c(1, 3, 4)

      i <- 1
      repeat{
      # sampling
      test <- sample(pool, N, replace=FALSE)

      # search N length of sequence and compare it
      search_seq_length <- length(search_seq)
      test_length <- length(test)

      for (j in 1:(test_length - search_seq_length + 1)){
      tmp_seq <- test[j:(j+search_seq_length-1)]

      if (all(tmp_seq == search_seq)) {
      print(paste0("===", i, "th sampling==="))
      print(paste0("---", j, "th sequence"))
      print(tmp_seq)
      break
      }

      }
      if (all(tmp_seq == search_seq)) break
      i <- i+1
      }

      print('=== test ===')
      print(test)

      # write.table() 함수 참조 => https://rfriend.tistory.com/17