MEP28: Axes.boxplot에서 복잡성 제거 #

상태 번호

논의

브랜치 및 풀 리퀘스트 #

다음은 이 MEP와 관련된 공개 PR 또는 분기 목록입니다.

  1. 다음 에서 중복된 통계 kwargs 사용 중단 Axes.boxplot: https://github.com/phobson/matplotlib/tree/MEP28-initial-deprecations

  2. 중복 스타일 옵션 사용 중단 Axes.boxplot: https://github.com/phobson/matplotlib/tree/MEP28-initial-deprecations

  3. 2D NumPy 배열을 입력으로 전달하지 않음: 없음

  4. 전처리 및 후처리 옵션 추가 cbook.boxplot_stats: https://github.com/phobson/matplotlib/tree/boxplot-stat-transforms

  5. cbook.boxplot_statskwargs 를 통한 노출 Axes.boxplot: 없음

  6. 다음 에서 중복된 통계적 kwargs 제거 Axes.boxplot: 없음

  7. 중복 스타일 옵션 제거 Axes.boxplot: 없음

  8. 나머지 논의사항 : 없음

초록 #

지난 몇 번의 릴리스에서 Axes.boxplot완전히 사용자 지정 가능한 아티스트 스타일 지정 및 통계 계산을 지원하기 위해 메서드가 복잡해졌습니다. 이로 인해 Axes.boxplot여러 부분으로 분리됩니다. 상자 그림을 그리는 데 필요한 통계는 에서 계산되는 cbook.boxplot_stats반면 실제 아티스트는 에서 그려집니다 Axes.bxp. 원래 방법 은 사용자 제공 데이터를 에 전달하고 , 결과를 에 제공하고, boxplot 플롯의 각 측면에 대한 스타일 정보를 전처리 Axes.boxplot하는 가장 공개적인 API로 남아 있습니다.cbook.boxplot_statsAxes.bxp

이 MEP는 합당한 이전 버전과의 호환성을 유지하면서 추가된 복잡성을 롤백하고 API를 단순화하기 위한 경로를 설명합니다.

자세한 설명 #

현재 이 Axes.boxplot방법은 사용자가 플롯에 그려질 각 상자에 대한 중앙값과 신뢰 구간을 지정할 수 있는 매개변수를 허용합니다. 이는 고급 사용자가 matplotlib에서 제공하는 간단한 방법과 다른 방식으로 계산된 통계를 제공할 수 있도록 제공되었습니다. 그러나 이 입력을 처리하려면 데이터 구조의 형식이 그려야 하는 것과 일치하는지 확인하는 복잡한 논리가 필요합니다. 현재 이 논리에는 for 루프를 사용하여 최대 5단계까지 중첩된 9개의 개별 if/else 문이 포함되어 있으며 최대 2개의 오류가 발생할 수 있습니다. Axes.bxp이러한 매개변수는 관련 통계가 포함된 사전 목록에서 상자 그림을 그리는 방법을 만들기 전에 추가되었습니다 . Matplotlib는 또한 다음을 통해 이러한 통계를 계산하는 함수를 제공합니다.cbook.boxplot_stats. 이제 고급 사용자는 a) 에 필요한 통계를 계산하는 자체 함수를 작성 Axes.bxp하거나 b) 에서 반환된 출력을 수정 cbook.boxplots_stats 하여 플롯 아티스트의 위치를 ​​완전히 사용자 지정할 수 있습니다. 이러한 유연성을 통해 중앙값과 해당 신뢰 구간만 수동으로 지정하는 매개변수는 이전 버전과의 호환성을 위해 유지됩니다.

의 두 가지 역할이 계산용과 그리기 용 Axes.boxplot으로 분할된 것과 거의 동시에 상자 그림의 모든 구성 요소 그리기를 개별적으로 토글하는 매개변수 와 해당 아티스트의 스타일을 개별적으로 구성하는 매개변수를 허용하도록 작성되었습니다. 그러나 이전 버전과의 호환성을 유지하기 위해 매개변수(이전에 전단지의 기호를 지정하는 데 사용됨)는 그대로 유지되었습니다. 이 매개변수 자체에는 에서 지정한 기본 스타일 의 새 매개변수와 매개변수 를 조정하는 상당히 복잡한 논리가 필요합니다 .cbook.boxplot_statsAxes.bxpAxes.boxplotAxes.bxpsymsymflierpropsmatplotlibrc

이 MEP는 초보자와 고급 사용자 모두를 위해 상자 그림 생성을 극적으로 단순화하려고 합니다. 여기서 제안된 변경 사항은 seaborn과 같은 다운스트림 패키지에서도 사용할 수 있습니다. seaborn은 사용자가 seaborn API를 통해 매개 변수의 임의 사전을 기본 matplotlib 함수에 전달할 수 있도록 현명하게 허용하기 때문입니다.

이는 다음과 같은 방법으로 달성됩니다.

  1. cbook.boxplot_stats사전 및 사후 계산 변환 함수가 전달될 수 있도록 수정됩니다(예: 로그 정규 분포 데이터의 경우) np.log .np.exp

  2. Axes.boxplot그것들을 수락하고 순진하게 전달하도록 수정될 것입니다 cbook.boxplots_stats(Alt: stat 함수와 선택적 매개변수의 사전 전달).

  3. 의 오래된 매개변수 Axes.boxplot는 더 이상 사용되지 않으며 나중에 제거됩니다.

중요성 #

위스커의 한계는 산술적으로 계산되기 때문에 상자 및 위스커 플롯에는 정규성에 대한 암묵적인 가정이 있습니다. 이것은 주로 이상값으로 분류되는 데이터 포인트에 영향을 미칩니다.

상자 그림을 그리는 데 사용되는 데이터 및 결과에 대한 변환을 허용하면 데이터가 정규 분포에 적합하지 않은 것으로 알려진 경우 사용자가 해당 가정을 거부할 수 있습니다.

다음은 Axes.boxplot이러한 유형의 변환에 따라 로그 정규 데이터의 이상값을 다르게 분류하는 방법의 예입니다.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cbook
np.random.seed(0)

fig, ax = plt.subplots(figsize=(4, 6))
ax.set_yscale('log')
data = np.random.lognormal(-1.75, 2.75, size=37)

stats = cbook.boxplot_stats(data, labels=['arithmetic'])
logstats = cbook.boxplot_stats(np.log(data), labels=['log-transformed'])

for lsdict in logstats:
    for key, value in lsdict.items():
        if key != 'label':
            lsdict[key] = np.exp(value)

stats.extend(logstats)
ax.bxp(stats)
fig.show()

( 소스 코드 , png )

../../_images/MEP28-1.png

구현 #

변환 함수를 cbook.boxplots_stats# 에 전달

이 MEP는 두 개의 매개변수(예: transform_intransform_outboxplot 함수에 대한 통계를 계산하는 요리책 함수에 추가됨)를 제안합니다. 이들은 선택적 키워드 전용 인수이며 사용자가 생략할 때 쉽게 no-op로 설정할 수 있습니다. 함수가 전달된 데이터의 각 하위 집합을 통해 루프를 돌 때 함수가 데이터에 적용됩니다 . 통계 사전 목록이 계산된 후 함수는 사전의 각 값에 적용됩니다.lambda x: xtransform_inboxplot_statstransform_out

그런 다음 이러한 변환 Axes.boxplot을 해당 메서드의 복잡성에 거의 영향을 주지 않고 호출 서명에 추가할 수 있습니다. 에 직접 전달할 수 있기 때문 cbook.boxplot_stats입니다. 또는 Axes.boxplot선택적 통계 함수 kwarg 및 직접 전달될 매개변수 사전을 허용하도록 수정될 수 있습니다.

구현의 이 시점에서 사용자와 seaborn과 같은 외부 라이브러리는 Axes.boxplot메서드를 통해 완전한 제어를 가집니다. 더 중요한 것은 적어도 seaborn은 사용자가 이러한 새로운 옵션을 활용할 수 있도록 API를 변경할 필요가 없다는 것입니다.

Axes.boxplotAPI 및 기타 기능 단순화 #

boxplot 방법을 단순화하는 것은 주로 사용 중단 후 중복 매개변수를 제거하는 것으로 구성됩니다. Axes.boxplot 선택적으로 다음 단계에는 와 사이의 사소한 용어 불일치를 수정하는 작업이 포함됩니다 Axes.bxp.

더 이상 사용되지 않고 제거될 매개변수는 다음과 같습니다.

  1. usermedians- 10 SLOC, 3 if블록, for루프 로 처리

  2. conf_intervals- 15개의 SLOC, 6개의 if블록, for루프 로 처리

  3. sym- 12개의 SLOC, 4 if블록 으로 처리

옵션을 제거하면 sym나머지 스타일링 매개변수를 처리하는 모든 코드를 로 이동할 수 Axes.bxp있습니다. 이것은 복잡성을 제거하지는 않지만 Axes.bxp, cbook.boxplot_stats, 및 간의 단일 책임 원칙을 강화합니다 Axes.boxplot.

또한 notch매개변수의 이름 shownotches 을 과 일치하도록 변경할 수 있습니다 Axes.bxp. 이러한 종류의 정리는 한 단계 더 나아가 새 매개변수 에 전달된 kwargs로 롤링될 수 있습니다 whis.bootstrapautorangestatfxn

이전 버전과의 호환성 #

이 MEP를 구현하면 결국 이전 버전과 호환되지 않으며 키워드 매개변수 usermedians, conf_intervals및 가 제거 sym됩니다. GitHub의 커서 검색에 따르면 usermedians, conf_intervals는 모두 matplotlib에 대한 매우 강력한 지식을 가지고 있는 것으로 보이는 소수의 사용자에 의해 사용됩니다. 강력한 사용 중단 주기는 이러한 사용자가 새 API로 마이그레이션할 수 있는 충분한 시간을 제공해야 합니다.

그러나 더 이상 사용되지 sym않으면 matplotlib 사용자 기반에 훨씬 더 광범위하게 도달할 수 있습니다.

일정 #

가속화된 타임라인은 다음과 같습니다.

  1. v2.0.1에 변환 추가 cbook.boxplots_stats, 노출Axes.boxplot

  2. v2.1.0 초기 지원 중단 및 2D NumPy 배열을 입력으로 사용

    1. 2D NumPy 배열을 입력으로 사용. 2D 배열 주변의 의미 체계는 일반적으로 혼란스럽습니다.

    2. usermedians, conf_intervals, sym매개변수

  3. v2.2.0

    1. usermedians, conf_intervals, sym매개변수 제거

    2. 다른 매개변수와 일관성을 유지하기 notch위해 지원 중단shownotchesAxes.bxp

  4. v2.3.0
    1. notch매개변수 제거

    2. 모든 스타일을 이동하고 아티스트가 논리를 전환하는 것은 Axes.bxp와 사이 의 Axes.boxplot 중개인에 지나지 않습니다.Axes.bxpcbook.boxplots_stats

사용자에게 예상되는 영향 #

위에 설명된 대로 더 이상 사용되지 않으며 usermedians소수의 conf_intervals 사용자에게 영향을 미칠 수 있습니다. 영향을 받을 사용자는 거의 확실하게 변화에 적응할 수 있는 고급 사용자입니다.

sym옵션을 사용하지 않으면 더 많은 사용자를 가져올 수 있으며 이에 대한 커뮤니티 피드백을 수집하기 위해 노력해야 합니다.

다운스트림 라이브러리에 예상되는 영향 #

소스 코드(2016년 10월 17일 현재 GitHub 마스터)는 seaborn 및 python-ggplot에 대해 검사되어 이러한 변경 사항이 사용에 영향을 미치는지 확인했습니다. 이 MEP에서 제거하도록 지정된 매개변수는 seaborn에서 사용되지 않습니다. matplotlib의 boxplot 기능을 사용하는 seaborn API는 사용자가 **kwargsmatplotlib의 API를 통해 임의로 전달할 수 있도록 합니다. 따라서 최신 matplotlib 설치를 사용하는 노련한 사용자는 이 MEP의 결과로 추가된 새로운 기능을 최대한 활용할 수 있습니다.

Python-ggplot은 boxplot을 그리는 자체 기능을 구현했습니다. 따라서 이 MEP를 구현한 결과로 영향을 받을 수 없습니다.

대안 #

테마의 변형 #

이 MEP는 느슨하게 결합된 몇 가지 구성 요소로 나눌 수 있습니다.

  1. 사전 및 사후 계산 변환 기능 허용cbook.boxplot_stats

  2. Axes.boxplotAPI 에서 해당 변환 노출

  3. 중복 통계 옵션 제거Axes.boxplot

  4. 모든 스타일링 매개변수 처리를 에서 Axes.boxplot로 전환합니다 Axes.bxp.

이 접근 방식을 사용하면 #2가 종속되고 #1과 #4가 #3에 종속됩니다.

#2에 대한 두 가지 접근 방식이 있습니다. 첫 번째이자 가장 직접적인 방법은 in 의 new transform_intransform_out매개변수 를 미러링 하고 직접 전달하는 것입니다.cbook.boxplot_statsAxes.boxplot

두 번째 방법은 statfxnstatfxn_args 매개변수를 에 추가하는 것 Axes.boxplot입니다. 이 구현에서 의 기본값은 statfxn이지만 cbook.boxplot_stats사용자는 자신의 기능을 전달할 수 있습니다. 그러면 transform_inand transform_out가 매개변수의 요소로 전달됩니다 statfxn_args.

def boxplot_stats(data, ..., transform_in=None, transform_out=None):
    if transform_in is None:
        transform_in = lambda x: x

    if transform_out is None:
        transform_out = lambda x: x

    output = []
    for _d in data:
        d = transform_in(_d)
        stat_dict = do_stats(d)
        for key, value in stat_dict.item():
            if key != 'label':
                stat_dict[key] = transform_out(value)
        output.append(d)
    return output


 class Axes(...):
     def boxplot_option1(data, ..., transform_in=None, transform_out=None):
         stats = cbook.boxplot_stats(data, ...,
                                     transform_in=transform_in,
                                     transform_out=transform_out)
         return self.bxp(stats, ...)

     def boxplot_option2(data, ..., statfxn=None, **statopts):
         if statfxn is None:
             statfxn = boxplot_stats
         stats = statfxn(data, **statopts)
         return self.bxp(stats, ...)

두 경우 모두 사용자가 다음을 수행할 수 있습니다.

fig, ax1 = plt.subplots()
artists1 = ax1.boxplot_optionX(data, transform_in=np.log,
                               transform_out=np.exp)

my_box_stats그러나 옵션 2를 사용하면 멋진 BCA 신뢰 구간과 수염이 데이터의 일부 특성에 따라 다르게 설정된 완전히 사용자 정의 통계 함수(예: )를 작성할 수 있습니다 .

이는 현재 API에서 사용할 수 있습니다.

fig, ax1 = plt.subplots()
my_stats = my_box_stats(data, bootstrap_method='BCA',
                        whisker_method='dynamic')
ax1.bxp(my_stats)

옵션 2를 사용하면 더 간결해질 것입니다.

fig, ax = plt.subplots()
statopts = dict(transform_in=np.log, transform_out=np.exp)
ax.boxplot(data, ..., **statopts)

사용자는 자신의 함수를 전달하여 통계를 계산할 수도 있습니다.

fig, ax1 = plt.subplots()
ax1.boxplot(data, statfxn=my_box_stats, bootstrap_method='BCA',
            whisker_method='dynamic')

위의 예에서 옵션 2는 미미한 이점만 있는 것처럼 보이지만 seaborn과 같은 다운스트림 라이브러리의 맥락에서 다음과 같은 이점이 seaborn에 대한 패치 없이 가능하므로 이점이 더 분명합니다.

import seaborn
tips = seaborn.load_data('tips')
g = seaborn.factorplot(x="day", y="total_bill", hue="sex", data=tips,
                       kind='box', palette="PRGn", shownotches=True,
                       statfxn=my_box_stats, bootstrap_method='BCA',
                       whisker_method='dynamic')

이러한 유형의 유연성은 현재 세 가지 기능에서 전체 boxplot API를 분할하려는 의도였습니다. 그러나 실제로 seaborn과 같은 다운스트림 라이브러리는 분할 이전으로 거슬러 올라가는 matplotlib 버전을 지원합니다. 따라서 유연성을 조금 더 추가 Axes.boxplot하면 다운스트림 라이브러리 관리자의 개입 없이 최신 matplotlib 설치를 통해 다운스트림 라이브러리 사용자에게 모든 기능을 노출할 수 있습니다.

적게 하기 #

또 다른 명백한 대안은 및 에서 추가된 사전 및 사후 계산 변환 기능을 생략하고 cbook.boxplot_stats위에서 Axes.boxplot설명한 대로 중복 통계 및 스타일 매개변수를 간단히 제거하는 것입니다.

아무것도 안하고 #

인생의 많은 일과 마찬가지로 아무것도 하지 않는 것도 선택 사항입니다. 이것은 우리가 단순히 사용자와 다운스트림 라이브러리 사이의 분할을 활용 cbook.boxplot_stats하고 Axes.bxp그에 대한 인터페이스를 제공하는 방법을 결정할 수 있도록 옹호한다는 것을 의미합니다.