일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- reverse v.s. reversed
- functools.wraps
- PIP
- decorator
- sort(reverse=True) v.s. reverse
- [초급(예비) 개발자 오픈소스 실무 역량강화 교육]
- Python
- 순수함수
- OS
- os.path
- r-string
- selenium-wire
- boto3
- 생각
- Airflow
- CI/CD
- slicing [::-1]
- 함수형 프로그래밍
- 쿼리
- ds_store
- 코딩 테스트
- timestamp
- 고차함수
- sort v.s. sorted
- S3
- pandas
- blinker
- Today
- Total
공부일지
[Python] Pandas Timestamp 관련 자주 쓰일 3가지 본문
작성일: 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]
돌아보며
근본적인 원인은 코드 수정 당시 급한 디버깅을 하고(아마 포매팅 부분만)
분기처리에 통일성을 둘 생각을 못 했기 때문이었던 것 같다.
다음에 코드 수정을 할 때에는
전체 맥락과 변수 바인딩에 대해 함께 고민하는 게 좋겠다.