본문 바로가기
재미로 하는 코딩

시각화 뽀개기12

by 헬푸밍 2023. 3. 23.

Visualizing statistical relationships(통계적 관계 시각화)

Emphasizing continuity with line plots(라인그래프로 연속성 강조)

산점도는 매우 효과적이지만 보편적으로 최적의 시각화 유형은 없다. 대신, 시각 표현은 데이터셋의 구체적인사항과 플롯으로 답변하고자 하는 문제에 맞게 조정되어야 한다!

 

몇몇 데이터셋으로 한 변수의 변화를 시간의 함수로나 비슷한 연속적인 변수로 이해하고자 할 수 있다. 이런 경우 좋은 선택지는 라인 플롯을 그리는 것이다. seaborn에서 lineplot()함수나 replot()에 kind='line'으로 해서 해낼 수 있다!

 

다우존스 데이터로 라인 그래프를 그릴건데...

dowjones = sns.load_dataset("dowjones")
dowjones

이렇게 한 50년넘는 달별 다우존스 지수 데이터 같다!

 

x는 날짜로하고, y를 가격으로 해서 라인 그래프를 그려보면...

sns.relplot(data=dowjones, x="Date", y="Price", kind="line");

날짜별 다우존스 가격을 볼 수 있는 그래프가 만들어진다!

 

Aggregation and representing uncertainty(집계와 불확실성 표현)

더 복잡한 데이터셋은 x변수의 동일한 값에 대해 다수 측정치를 가진다. seaborn의 기본 동작은 평균과 평균의 95% 신뢰구간을 그림으로 각 x변수의 여러개 측정치를 집계하는 것이다.

fmri 데이터 셋을 일단 보자!

fmri = sns.load_dataset("fmri")
fmri

이런 데이터셋이고...

 

timepoint값을 보면...

fmri['timepoint'].value_counts()

같은 값이 56개씩 있다!

 

x는 timepoint, y는 signal로 해서 라인그래프를 그려보면...

fmri = sns.load_dataset("fmri")
sns.relplot(data=fmri, x="timepoint", y="signal", kind="line")

56개의 값이 집계되서 그려진다!

 

신뢰구간은 부트스트래핑을 사용해 계산되어서... 큰 데이터 셋에서는 시간이 오래걸릴 수 있다. 그래서 없앨 수 도 있다.

위의 그래프에서 errorbar=None으로 지정해 주면....

sns.relplot(
    data=fmri, kind="line",
    x="timepoint", y="signal", errorbar=None,
);

신뢰구간이 사라진다!

 

특히 큰 데이터에 대한 좋은 선택지는 신뢰구간 대신 표준편차를 그려서 각 timepoint에서 분포의 퍼짐을 표시하는 것이다.

errorbar을 sd로 지정해주면...

sns.relplot(
    data=fmri, kind="line",
    x="timepoint", y="signal", errorbar="sd",
);

표준편차가 그려진다!

 

집계를 모두 끄려면, estimator파라미터를 None으로 바꾸자! 데이터가 각 점에서 다수의 관찰값을 가질 때에는 이상한 효과를 낼 수 있다!

sns.relplot(
    data=fmri, kind="line",
    x="timepoint", y="signal",
    estimator=None,
)

이렇게 그래프가 이상하게 그려진다!

 

Plotting subsets of data with semantic mappings

(시맨틱 매핑으로 데이터의 부분집합 그리기)

lineplot()함수는 scatterplot()과 같은 유연성을 가지고 있다. plot요소의 hue, size, style을 수정함으로서 3개까지 변수를 추가할 수 있다! scatterplot()과 같은 API를 해서 matplotlib에서 선과 점의 모양을 조절하는 파라미터에 대해 멈추고 생각할 필요가 없다.

 

lineplot()에서 시맨틱을 사용하는 것은 데이터가 집계되는 방식을 결정한다. 예를 들어 2가지 수준을 가진 hue시맨틱을 추가하는 것은 그림을 2개의 선과 에러 띠로 나눠서 각각 일치하는 데이터의 부분집합을 나타내도록 색칠한다.

hue에 event를 지정해주면...

이렇게 그려진다!

 

style시맨틱을 추가하면 기본값으로 선의 대쉬 패턴을 바꿔준다!

이번에는 hue에 region을 지정해주고, style을 event로 해주면...

sns.relplot(
    data=fmri, kind="line",
    x="timepoint", y="signal",
    hue="region", style="event",
);

이렇게 hue시맨틱은 색으로 region을 구별해주고, style시맨틱은 실선과 대시선으로 event를 구별해준다!

대시와 함께 또는 대시 대신에 각 관찰에서 사용된 마커로 부분 집합을 구별할수도 있다!

위 그래프에서 dashes=False, makers=True로 지정해주면...

sns.relplot(
    data=fmri, kind="line",
    x="timepoint", y="signal", hue="region", style="event",
    dashes=False, markers=True,
);

이렇게 대시 대신 marker로 구별가능해지고...

 

둘다 True로 지정하면...

sns.relplot(
    data=fmri, kind="line",
    x="timepoint", y="signal", hue="region", style="event",
    dashes=True, markers=True,
);

마커와 대시를 두개 모두 사용해서 구별할 수도 있다!

 

산점도와 같이 다수의 시맨틱을 사용해 라인 그래프를 그리는 것을 주의해야한다. 때때로는 유용할 수 있지만... 분석하고 해석하기 어려울 수도 있다! 단지 하나의 추가 변수의 변화를 검토할 때도 선의 색과 스타일을 모두 변경하는 것이 유용할 수 있다. 그러면 흑백으로 인쇄되거나 색맹인 사람이 볼때 더 쉽게 이해할 수 있다.

hue와 style모두에 event를 지정하면...

sns.relplot(
    data=fmri, kind="line",
    x="timepoint", y="signal", hue="event", style="event",
);

이렇게 색과 스타일 모두로 구별할 수 있다!

 

반복 측정 데이터로 작업할 때(즉 여러번 샘플링된 단위가 있을 때), 시맨틱을 통해 구별하지 않고 각 샘플링 단위를 분리해서 그릴 수 있다 이러면 범례가 복잡해지는 것을 막을 수 있다.

query를 이용해 event는 stim인 것만 뽑고...

units는 subject로 해주면...

sns.relplot(
    data=fmri.query("event == 'stim'"), kind="line",
    x="timepoint", y="signal", hue="region",
    units="subject", estimator=None,
);

subject별로 하나하나 다 그릴 수 있다!

 

lineplot()의 기본 컬러맵과 범례처리는 또한 hue시맨틱이 범주형인지 수치형인지에 따라 달라진다.

이번엔 dots 데이터셋을 이용할건데...

dots에서 align컬럼이 dots인 것만 보자!

dots = sns.load_dataset("dots").query("align == 'dots'")
dots

요런 데이터로...

x는 time, y는 firing_rate, hue는 coherance, style은 choice로 라인그래프를 그리면...

sns.relplot(
    data=dots, kind="line",
    x="time", y="firing_rate",
    hue="coherence", style="choice",
);

이렇게 차원이 총 4개인 그래프가 그려지게 된다!

 

hue변수가 수치형임에도 불구하고, 선형 색상 스케일로는 잘 표현되지 않을수도 있다. 이 경우에서 그런데... hue 변수의 수준이 로그 스케일이기 인 경우이다. 리스트나 딕셔너리 형태로 각 선에 특정 컬러값을 제공할 수 있다.

 

위 그래프에 팔레트를 직접 지정해주면...

palette = sns.cubehelix_palette(light=.8, n_colors=6)
sns.relplot(
    data=dots, kind="line",
    x="time", y="firing_rate",
    hue="coherence", style="choice", palette=palette,
)

전체적인 색상이 조금은 더 진해져서 조금은 더 잘 알아볼 수 있게 된다!

 

아니면 색상표가 정규화되는 방식을 변경할 수 도 있다.

이렇게 LogNorm을 import해서

coherance가 0이상인 것에다만 hue_norm=LogNorm()을 지정해주면...

from matplotlib.colors import LogNorm
palette = sns.cubehelix_palette(light=.7, n_colors=6)
sns.relplot(
    data=dots.query("coherence > 0"), kind="line",
    x="time", y="firing_rate",
    hue="coherence", style="choice",
    hue_norm=LogNorm(),
)

0이었던 것은 사라지고...

이렇게 그려진다...

 

3번째 시맨틱인 크기는 선의 넓이를 바꾼다!

hue대신 size에 coherence를 넣어주면...

sns.relplot(
    data=dots, kind="line",
    x="time", y="firing_rate",
    size="coherence", style="choice",
)

선의 굵기로 coherence를 분별할 수 있다!

 

size변수는 보통 수치형일 것이지만, 범주형데이터를 선의 굵기로 매핑하는 것도 가능하다. 범주형 데이터를 선의 굵기로 매핑할 때에는 주의해야 하는데... 두꺼운 선과 가는선 보다 구별하기 훨씬 어려울수 있기 때문이다. 그러나 대시선은 선이 높은 빈도의 변동성을 가질 때에는 인식하기 어렵기 때문에 다른 굵기를 사용하는 것은 이 경우에는 효과적이다!

이렇게 size에 choice를 넣어주면...

sns.relplot(
    data=dots, kind="line",
    x="time", y="firing_rate",
    hue="coherence", size="choice", palette=palette,
);

최종적으로 가장 접근성이 좋은 그래프가 완성된다!

 

Controlling sorting and orientation(정렬과 방향제어)

lineplot()은 가장 자주 y를 x의 함수로 그린다고 가정하기 때문에, 플로팅 하기 전에 x로 데이터를 분류하는 것이 기본값이다. 그러나 분류를 안할 수도 있다!

healthexp데이터를 Year로 분류한 데이터를 그릴것인데...

healthexp = sns.load_dataset("healthexp").sort_values("Year");
healthexp

이런 데이터 셋을 가지고...

x는 Spending_USD, y는 Life_Expectancy, hue는 Country로하면서...

sort=False로 그려주면...

Spending_USD에 대한 분류 없이 그려지고...(잘 이해는 못했다..)

 

y축을 따라 집계하는 것도 가능하다!

fmri에서 x는 signal, y는 timepoint, hue는 event로 그래프를 그리면...

sns.relplot(
    data=fmri, kind="line",
     x="signal", y="timepoint", hue="event"
);

이렇게 엉망으로 그려지는데...

 

orient='y'를 지정해주면 y값 기준 집계를 해서...

sns.relplot(
    data=fmri, kind="line",
     x="signal", y="timepoint", hue="event",
    orient="y",
);

깔끔하게 볼 수 있다!


참고사이트

https://seaborn.pydata.org/tutorial/relational.html#emphasizing-continuity-with-line-plots

 

Visualizing statistical relationships — seaborn 0.12.2 documentation

Visualizing statistical relationships Statistical analysis is a process of understanding how variables in a dataset relate to each other and how those relationships depend on other variables. Visualization can be a core component of this process because, w

seaborn.pydata.org

 

'재미로 하는 코딩' 카테고리의 다른 글

시각화 뽀개기13  (0) 2023.03.30
numpy를 사용한 이미지 압축해보기!  (2) 2023.03.30
시각화 뽀개기11  (0) 2023.03.19
다이아몬드 가격 예측해보기  (4) 2023.03.19
시각화 뽀개기10  (0) 2023.03.16

댓글