DataFrame에서 바로 그리기
지윤은 팀원들에게 Plotly Express의 가장 편리한 기능부터 보여주기로 했습니다. 바로 DataFrame을 함수에 그대로 넣는 것입니다.
import plotly.express as pximport pandas as pddf = px.data.iris()fig = px.scatter(df, x="sepal_width", y="sepal_length")fig.show()
딱 세 줄입니다. DataFrame을 만들고, 어느 열을 x축과 y축으로 쓸지 이름만 적으면 됩니다. 열 이름을 문자열로 전달하기 때문에 오타만 조심하면 됩니다.
px 함수에 DataFrame 전달하기
plotly.express의 모든 차트 함수는 첫 번째 인자로 DataFrame을 받습니다. 그 뒤에 어느 열을 어느 축에 매핑할지 지정합니다.
# 새 파일: chapter04_01_dataframe.pyimport plotly.express as pximport pandas as pd# 내장 데이터셋 활용df = px.data.iris()print(df.head())print(df.columns.tolist())
실행하면 열 이름 목록이 출력됩니다.
sepal_length sepal_width petal_length petal_width species species_id
0 5.1 3.5 1.4 0.2 setosa 1
...
['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species', 'species_id']
이제 열 이름을 그대로 x, y에 넣습니다.
# 수정: chapter04_01_dataframe.pyimport plotly.express as pximport pandas as pddf = px.data.iris()# 기본 산점도: x축=sepal_width, y축=sepal_length, 색상=speciesfig = px.scatter( df, x="sepal_width", y="sepal_length", color="species", size="petal_length", hover_data=["petal_width"], title="붓꽃 품종별 꽃받침 크기 분포")fig.show()
세 품종이 색으로 구분되고, 점의 크기가 꽃잎 길이에 비례하는 버블 산점도가 나타납니다. 마우스를 올리면 꽃잎 너비까지 확인할 수 있습니다.
color="species"를 추가하면 품종별로 색을 자동으로 구분해줍니다. size="petal_length"를 추가하면 꽃잎 길이에 따라 점의 크기가 달라집니다. 열 이름 하나만 더 적었을 뿐인데 차트가 훨씬 풍부해집니다.
와이드폼과 롱폼 데이터
데이터를 받다 보면 같은 정보를 두 가지 형태로 저장한 파일을 만나게 됩니다. 어떤 형태냐에 따라 px 함수를 쓰는 방법이 달라집니다.
와이드폼(Wide-form)은 각 카테고리가 별도의 열로 들어있습니다.
월 서울 부산 대구
1월 2.5 5.2 4.8
2월 3.1 5.8 5.3
3월 7.2 9.1 8.7
롱폼(Long-form)은 카테고리를 하나의 열로 묶고 값을 다른 열에 넣습니다.
월 도시 기온
1월 서울 2.5
1월 부산 5.2
1월 대구 4.8
2월 서울 3.1
...
Plotly Express는 롱폼을 선호합니다. color, facet_col 같은 파라미터가 하나의 열에서 카테고리를 읽어오기 때문입니다.
# 수정: chapter04_01_dataframe.pyimport plotly.express as pximport pandas as pddf = px.data.iris()fig = px.scatter( df, x="sepal_width", y="sepal_length", color="species", size="petal_length", hover_data=["petal_width"], title="붓꽃 품종별 꽃받침 크기 분포")fig.show()# 와이드폼 예시wide_df = pd.DataFrame({ "월": ["1월", "2월", "3월", "4월", "5월"], "서울": [2.5, 3.1, 7.2, 13.5, 18.9], "부산": [5.2, 5.8, 9.1, 14.3, 19.2], "대구": [4.8, 5.3, 8.7, 14.8, 20.1],})# 와이드폼을 px.line에 바로 넣으면: y에 여러 열을 리스트로 전달fig_wide = px.line( wide_df, x="월", y=["서울", "부산", "대구"], title="월별 평균 기온 (와이드폼)")fig_wide.show()
월별 세 도시의 기온 변화를 세 개의 선으로 표시한 선 그래프가 나타납니다.
와이드폼에서 y에 열 이름 리스트를 넘기면 각 열이 하나의 선으로 그려집니다. 간단하지만, 색상 구분이나 추가 정보를 넣기가 어렵습니다.
pd.melt()로 롱폼 변환하기
와이드폼을 롱폼으로 바꾸는 도구가 pd.melt()입니다.
# 수정: chapter04_01_dataframe.pyimport plotly.express as pximport pandas as pddf = px.data.iris()fig = px.scatter( df, x="sepal_width", y="sepal_length", color="species", size="petal_length", hover_data=["petal_width"], title="붓꽃 품종별 꽃받침 크기 분포")fig.show()wide_df = pd.DataFrame({ "월": ["1월", "2월", "3월", "4월", "5월"], "서울": [2.5, 3.1, 7.2, 13.5, 18.9], "부산": [5.2, 5.8, 9.1, 14.3, 19.2], "대구": [4.8, 5.3, 8.7, 14.8, 20.1],})fig_wide = px.line( wide_df, x="월", y=["서울", "부산", "대구"], title="월별 평균 기온 (와이드폼)")fig_wide.show()# pd.melt()로 롱폼 변환long_df = pd.melt( wide_df, id_vars=["월"], # 유지할 열 var_name="도시", # 카테고리 열 이름 value_name="기온" # 값 열 이름)print(long_df)# 롱폼으로 더 풍부한 차트 만들기fig_long = px.line( long_df, x="월", y="기온", color="도시", # 도시별로 색 구분 markers=True, title="월별 평균 기온 (롱폼)")fig_long.show()
롱폼으로 변환한 뒤 그린 선 그래프입니다. 서울, 부산, 대구가 색으로 구분되고, 데이터 포인트마다 마커가 표시됩니다. 마우스를 올리면 해당 도시의 기온을 확인할 수 있습니다.
롱폼으로 바꾸고 나면 color="도시"처럼 열 이름 하나로 색을 구분할 수 있습니다. 데이터가 늘어나도 코드는 바뀌지 않습니다.
DataFrame.plot() vs px 함수 비교
Matplotlib을 쓰던 시절에는 df.plot()으로 차트를 그렸습니다. 이제 Plotly도 df.plot(backend='plotly')를 지원합니다. 하지만 두 방식은 목적이 다릅니다.
# 수정: chapter04_01_dataframe.pyimport plotly.express as pximport pandas as pddf = px.data.iris()fig = px.scatter( df, x="sepal_width", y="sepal_length", color="species", size="petal_length", hover_data=["petal_width"], title="붓꽃 품종별 꽃받침 크기 분포")fig.show()wide_df = pd.DataFrame({ "월": ["1월", "2월", "3월", "4월", "5월"], "서울": [2.5, 3.1, 7.2, 13.5, 18.9], "부산": [5.2, 5.8, 9.1, 14.3, 19.2], "대구": [4.8, 5.3, 8.7, 14.8, 20.1],})fig_wide = px.line( wide_df, x="월", y=["서울", "부산", "대구"], title="월별 평균 기온 (와이드폼)")fig_wide.show()long_df = pd.melt( wide_df, id_vars=["월"], var_name="도시", value_name="기온")fig_long = px.line( long_df, x="월", y="기온", color="도시", markers=True, title="월별 평균 기온 (롱폼)")fig_long.show()# DataFrame.plot()으로 Plotly 차트 그리기# pandas >= 1.0 + plotly 설치 필요pd.options.plotting.backend = "plotly"fig_plot = wide_df.set_index("월")[["서울", "부산", "대구"]].plot( title="월별 평균 기온 (df.plot 방식)")fig_plot.show()print("두 방식의 차이점:")print("df.plot(backend='plotly') : 빠른 탐색, 코드 최소화")print("px.line(df, ...) : 세밀한 제어, color/facet 등 추가 파라미터")
df.plot(backend='plotly')로 생성한 인터랙티브 선 그래프가 나타납니다. Matplotlib 스타일의 코드로 Plotly 차트를 빠르게 확인할 수 있습니다.
df.plot()은 기존 Matplotlib 코드를 빠르게 Plotly로 전환할 때 유용합니다. px 함수는 더 많은 옵션을 제공하고 Plotly의 기능을 완전히 활용할 수 있습니다.
실전: CSV 파일 읽어서 바로 시각화하기
이제 실제 CSV 파일을 읽어서 시각화해봅니다. Plotly에 내장된 tips 데이터를 CSV로 저장한 뒤 다시 읽어 사용합니다.
# 새 파일: chapter04_01_csv_practice.pyimport plotly.express as pximport pandas as pd# tips 데이터를 CSV로 저장 (실습용)df_tips = px.data.tips()df_tips.to_csv("tips.csv", index=False)# CSV 파일 읽기df = pd.read_csv("tips.csv")print(df.dtypes)print(df.shape)# 성별·흡연 여부별 팁 분포fig = px.scatter( df, x="total_bill", y="tip", color="sex", symbol="smoker", size="size", hover_data=["day", "time"], title="식사 금액과 팁의 관계")fig.show()# 요일별 평균 팁 막대 그래프fig2 = px.bar( df, x="day", y="tip", color="sex", barmode="group", category_orders={"day": ["Thur", "Fri", "Sat", "Sun"]}, title="요일별 팁 (성별 비교)")fig2.show()
첫번째 차트는 식사 금액과 팁의 관계를 보여주는 산점도로, 성별은 색으로, 흡연 여부는 마커 모양으로 구분됩니다. 두번째 차트는 요일별 팁을 성별로 비교한 막대 그래프입니다. 마우스를 올리면 요일, 시간대 정보까지 확인할 수 있습니다.
CSV를 읽자마자 dtypes로 열 타입을 확인하는 습관을 갖는 것이 좋습니다. 숫자 열이 문자열로 읽힌다면 pd.to_numeric()으로 변환해야 합니다.