4 minute read

PandasDataFrameOutputParser

Pandas DataFrame은 Python 프로그래밍 언어에서 널리 사용되는 데이터 구조로, 데이터 조작 및 분석을 위한 강력한 도구입니다. DataFrame은 구조화된 데이터를 효과적으로 다루기 위한 포괄적인 도구 세트를 제공하며, 이를 통해 데이터 정제, 변환 및 분석과 같은 다양한 작업을 수행할 수 있습니다.

출력 파서는 사용자가 임의의 Pandas DataFrame을 지정하여 해당 DataFrame에서 데이터를 추출하고, 이를 형식화된 사전(dictionary) 형태로 조회할 수 있게 해주는 LLM(Large Language Model) 기반 도구입니다.

.env파일 우선 설정 필요

from dotenv import load_dotenv

load_dotenv()
True
# LangSmith 추적을 설정합니다. https://smith.langchain.com
# !pip install langchain-teddynote
from langchain_teddynote import logging

# 프로젝트 이름을 입력합니다.
logging.langsmith("CH03-OutputParser")
LangSmith 추적을 시작합니다.
[프로젝트명]
CH03-OutputParser
import pprint
from typing import Any, Dict

import pandas as pd
from langchain.output_parsers import PandasDataFrameOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
# ChatOpenAI 모델 초기화 (gpt-3.5-turbo 모델 사용을 권장합니다)
model = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo")

format_parser_output 함수는 파서 출력을 사전 형식으로 변환하고 출력 형식을 지정하는 데 사용됩니다.

# 출력 목적으로만 사용됩니다.
def format_parser_output(parser_output: Dict[str, Any]) -> None:
    # 파서 출력의 키들을 순회합니다.
    for key in parser_output.keys():
        # 각 키의 값을 딕셔너리로 변환합니다.
        parser_output[key] = parser_output[key].to_dict()
    # 예쁘게 출력합니다.
    return pprint.PrettyPrinter(width=4, compact=True).pprint(parser_output)
  • titanic.csv 데이터를 읽어온 뒤 DataFrame 을 로드하여 df 변수에 할당합니다.

  • PandasDataFrameOutputParser를 사용하여 DataFrame을 파싱합니다.

# 원하는 Pandas DataFrame을 정의합니다.
df = pd.read_csv("./data/titanic.csv")
df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
# 파서를 설정하고 프롬프트 템플릿에 지시사항을 주입합니다.
parser = PandasDataFrameOutputParser(dataframe=df)

# 파서의 지시사항을 출력합니다.
print(parser.get_format_instructions())
The output should be formatted as a string as the operation, followed by a colon, followed by the column or row to be queried on, followed by optional array parameters.
1. The column names are limited to the possible columns below.
2. Arrays must either be a comma-separated list of numbers formatted as [1,3,5], or it must be in range of numbers formatted as [0..4].
3. Remember that arrays are optional and not necessarily required.
4. If the column is not in the possible columns or the operation is not a valid Pandas DataFrame operation, return why it is invalid as a sentence starting with either "Invalid column" or "Invalid operation".

As an example, for the formats:
1. String "column:num_legs" is a well-formatted instance which gets the column num_legs, where num_legs is a possible column.
2. String "row:1" is a well-formatted instance which gets row 1.
3. String "column:num_legs[1,2]" is a well-formatted instance which gets the column num_legs for rows 1 and 2, where num_legs is a possible column.
4. String "row:1[num_legs]" is a well-formatted instance which gets row 1, but for just column num_legs, where num_legs is a possible column.
5. String "mean:num_legs[1..3]" is a well-formatted instance which takes the mean of num_legs from rows 1 to 3, where num_legs is a possible column and mean is a valid Pandas DataFrame operation.
6. String "do_something:num_legs" is a badly-formatted instance, where do_something is not a valid Pandas DataFrame operation.
7. String "mean:invalid_col" is a badly-formatted instance, where invalid_col is not a possible column.

Here are the possible columns:
```
PassengerId, Survived, Pclass, Name, Sex, Age, SibSp, Parch, Ticket, Fare, Cabin, Embarked
```

컬럼에 대한 값을 조회하는 예제입니다.

# 열 작업 예시입니다.
df_query = "Age column 을 조회해 주세요."


# 프롬프트 템플릿을 설정합니다.
prompt = PromptTemplate(
    template="Answer the user query.\n{format_instructions}\n{question}\n",
    input_variables=["question"],  # 입력 변수 설정
    partial_variables={
        "format_instructions": parser.get_format_instructions()
    },  # 부분 변수 설정
)

# 체인 생성
chain = prompt | model | parser

# 체인 실행
parser_output = chain.invoke({"question": df_query})

# 출력
format_parser_output(parser_output)
{'Age': {0: 22.0,
         1: 38.0,
         2: 26.0,
         3: 35.0,
         4: 35.0,
         5: nan,
         6: 54.0,
         7: 2.0,
         8: 27.0,
         9: 14.0,
         10: 4.0,
         11: 58.0,
         12: 20.0,
         13: 39.0,
         14: 14.0,
         15: 55.0,
         16: 2.0,
         17: nan,
         18: 31.0,
         19: nan}}

첫 번째 행을 검색하는 예시입니다.

# 행 조회 예시입니다.
df_query = "Retrieve the first row."

# 체인 실행
parser_output = chain.invoke({"question": df_query})

# 결과 출력
format_parser_output(parser_output)
{'0': {'Age': 22.0,
       'Cabin': nan,
       'Embarked': 'S',
       'Fare': 7.25,
       'Name': 'Braund, '
               'Mr. '
               'Owen '
               'Harris',
       'Parch': 0,
       'PassengerId': 1,
       'Pclass': 3,
       'Sex': 'male',
       'SibSp': 1,
       'Survived': 0,
       'Ticket': 'A/5 '
                 '21171'}}

특정 열에서 일부 행의 평균을 검색하는 작업 예제입니다.

# row 0 ~ 4의 평균 나이를 구합니다.
df["Age"].head().mean()
31.2
# 임의의 Pandas DataFrame 작업 예시, 행의 수를 제한합니다.
df_query = "Retrieve the average of the Ages from row 0 to 4."

# 체인 실행
parser_output = chain.invoke({"question": df_query})

# 결과 출력
print(parser_output)
{'mean': 31.2}

다음은 요금(Fare) 에 대한 평균 가격을 산정하는 예시입니다.

df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
# 잘못 형식화된 쿼리의 예시입니다.
df_query = "Calculate average `Fare` rate."

# 체인 실행
parser_output = chain.invoke({"question": df_query})

# 결과 출력
print(parser_output)
{'mean': 22.19937}
# 결과 검증
df["Fare"].mean()
22.19937

Written by: teddynote