공부일지

[Python] Pandas Timestamp 관련 자주 쓰일 3가지 본문

Computer/Trouble Shooting

[Python] Pandas Timestamp 관련 자주 쓰일 3가지

이르리의 공부일지 2024. 9. 22. 17:36

작성일: 2024-08-26

 

요약

상황

날짜 관련 변수를 다루는 분기처리에 타입 통일성을 두지 않아 버그 발생

 

공유

Python의 외장 라이브러리 Pandas의 시간 관련 메소드 Timestamp의 자주 쓰이는 기능 3가지를 알아보자.

1. 타입 확인

2. 문자열로 바꾸기

3. 내장 라이브러리 datetime의 객체로 바꾸기

 

 

상황


 이미지가 S3에 안 올라가는 문제가 있어서 디버깅을 했다.

아래는 문제를 해결하기 전 코드이다.

이미지 이름을 만들 때 변수 date를 넣는데 그쪽에 문제의 원인이 있다.

# before
for name in df['name'].unique():
  df_temp = df[df["name"] == name]
  date = df_temp["date"].unique()[0]date
  if type(date) == np.datetime64 :
      date = str(date).split('T')[0]
  if type(date) == str:
      date = datetime.strptime("-".join(re.split("/|-|\.", date)), "%Y-%m-%d").date()
  y = date.year
  m = date.month
  
  directory = f"image/{company}/{int(y)}/{int(m)}/{date}_{name.replace(':', '').replace('/', '-')}".strip()
# S3에 올릴 이미지 링크 이름에 date가 들어감.
...

date = datetime.strptime("-".join(re.split("/|-|\.", date)), "%Y-%m-%d").date()

...

 

이렇게 이미지 링크에 들어갈 변수(date)가

strptime의 특정 포맷("%Y-%m-%d")으로 돼있어서 문제를 일으켰을 거라고 생각했다.

시간(00:00:00)에 대한 처리를 안 해줬기 때문에...

 

디버거를 돌리고 조사식에 date 타입을 보니

Pandas의 Timestamp 메소드 때문에 에러가 발생했다고 떴다.

디버거 조사식

 

Timstamp 메소드에 대해 잘 알면 바로 고칠텐데

그런데 타입이 클래스명으로 뜨니 뭐라고 해야 조건을 달 수 있나 갑자기 떠오르지 않았다.

그래서  Python의 외장 라이브러리인 Pandas의 TimeStamp에 대해 다시 조사하였다.

아래는 그 내용을 정리하고 해결 파트에서 코드를 어떻게 수정했는지 정리해두겠다.

 

 

 

Timestamp 자주 쓸만한 기능 3가지


pandas._libs.tslibs.timestamps.Timestamp 타입은 pandas에서 사용하는 Timestamp 객체이다.

이 타입을 처리하거나 다른 형식으로 변환하려면 pandas의 기능을 활용할 수 있다.

 

1. 타입 확인

type(date)가 pandas._libs.tslibs.timestamps.Timestamp와 같은지 확인하는 방법

 

1) isinstance()를 사용하는 방법

import pandas as pd 

if isinstance(date, pd.Timestamp): 
	print("date는 Timestamp 타입입니다.")

 

2) type()을 사용하는 방법

import pandas as pd 

if type(date) == pd.Timestamp: 
	print("date는 Timestamp 타입입니다.")

 

 

2. Timestamp를 문자열로 변환

만약 Timestamp 객체를 문자열로 변환하고 싶다면

내장 라이브러리인 datetime의 메소드 strftime()을 사용할 수 있다.

 

예를 들어:

date_str = date.strftime("%Y-%m-%d")
print(date_str)

 

 

이는 Timestamp 객체를 "YYYY-MM-DD" 형식의 문자열로 변환해준다.

 

3. Timestamp를 datetime 객체로 변환

Timestamp 객체를 datetime 객체로 변환하고 싶다면 외장 라이브러리 Pandas의 메소드 to_pydatetime()를 사용할 수 있습니다:

date_dt = date.to_pydatetime()

 

 

이는 pandas.Timestamp를 datetime.datetime 객체로 변환해준다.

 

요약:

  • pandas.Timestamp 타입인지 확인하려면 내장 함수인 type()이나 isinstance()를 사용.
  • Timestamp를 문자열로 변환하려면 내장 라이브러리 datetime의 메소드 strftime() 사용.
  • Timestamp를 datetime으로 변환하려면 외장 라이브러리 Pandas의 메소드 to_pydatetime() 사용.

 

 

c.f.

type()

https://www.w3schools.com/python/python_datatypes.asp

 

W3Schools.com

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

 

isinstance()

https://www.w3schools.com/python/ref_func_isinstance.asp

 

W3Schools.com

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

 

datetime

https://docs.python.org/ko/3/library/datetime.html

 

datetime — Basic date and time types

Source code: Lib/datetime.py The datetime module supplies classes for manipulating dates and times. While date and time arithmetic is supported, the focus of the implementation is on efficient attr...

docs.python.org

 

 

Pandas 

https://pandas.pydata.org/docs/reference/api/pandas.Timestamp.to_pydatetime.html

 

pandas.Timestamp.to_pydatetime — pandas 2.2.3 documentation

Convert a Timestamp object to a native Python datetime object. If warn=True, issue a warning if nanoseconds is nonzero. Examples >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548') >>> ts.to_pydatetime() datetime.datetime(2020, 3, 14, 15, 32, 52, 192548) A

pandas.pydata.org

 

 

 

 

해결


# after
for name in df['name'].unique():
    df_temp = df[df["name"] == name]
    date = df_temp["date"].unique()[0]
    if type(date) == np.datetime64 :
        date = str(date).split('T')[0]
    elif type(date) == pd.Timestamp:
        date = str(date).split(' ')[0]

    y, m = date.split('-')[0:2]
    m = str(int(m))

    directory = f"image/{company}/{int(y)}/{int(m)}/{date}_{name.replace(':', '').replace('/', '-')}".strip()

 

수정 전에는 변수 date가 Timestamp 객체일 가능성이 없었고

String일 때 오히려 datetime으로  바꿔서 

어떤 건 String 객체이고 내가 분기처리한 부분은 datetime 객체가 되게 했다.

 

그러나 변경 후에는 

Timestamp 객체일 경우에 확실히 String 객체로 바꿔주어

분기처리 전체에서 date의 타입을 통일시켰다.

아래는 변경 전후의 코드 스니펫이다.

 # The snippet before debugging
 if type(date) == str:
      date = datetime.strptime("-".join(re.split("/|-|\.", date)), "%Y-%m-%d").date()
      
      
 # The snippet after debugging
    elif type(date) == pd.Timestamp:
        date = str(date).split(' ')[0]

 

 

 

돌아보며


 근본적인 원인은 코드 수정 당시 급한 디버깅을 하고(아마 포매팅 부분만)

분기처리에 통일성을 둘 생각을 못 했기 때문이었던 것 같다.

다음에 코드 수정을 할 때에는

전체 맥락과 변수 바인딩에 대해 함께 고민하는 게 좋겠다.