Почему боке не появляется?

таблица, над которой я работаю:

https://github.com/KeithGalli/pandas/blob/master/pokemon_data.csv

Когда я создаю диаграмму для столбца «HP» с категорией «Поколение», она работает нормально.

код ИЗОБРАЖЕНИЕ Бокс-сюжета ПРОИЗВОДСТВО:

def box_plot(df, vals, label, ylabel=None):

    """
    Make a Bokeh box plot from a tidy DataFrame.
    
    Parameters
    ----------
    df : tidy Pandas DataFrame
        DataFrame to be used for plotting
    vals : hashable object
        Column of DataFrame containing data to be used.
    label : hashable object
        Column of DataFrame use to categorize.
    ylabel : str, default None
        Text for y-axis label
        
    Returns
    -------
    output : Bokeh plotting object
        Bokeh plotting object that can be rendered with
        bokeh.io.show()
        
    Notes
    -----
    .. Based largely on example code found here:
     https://github.com/bokeh/bokeh/blob/master/examples/plotting/file/boxplot.py
    """
    # Get the categories
    cats = list(df[label].unique())
    
    # Group Data frame
    df_gb = df.groupby(label)

    # Compute quartiles for each group
    q1 = df_gb[vals].quantile(q=0.25)
    q2 = df_gb[vals].quantile(q=0.5)
    q3 = df_gb[vals].quantile(q=0.75)
                       
    # Compute interquartile region and upper and lower bounds for outliers
    iqr = q3 - q1
    upper_cutoff = q3 + 1.5*iqr
    lower_cutoff = q1 - 1.5*iqr

    # Find the outliers for each category
    def outliers(group):
        cat = group.name
        outlier_inds = (group[vals] > upper_cutoff[cat]) \
                                     | (group[vals] < lower_cutoff[cat])
        return group[vals][outlier_inds]

    # Apply outlier finder
    out = df_gb.apply(outliers).dropna()

    # Points of outliers for plotting
    outx = []
    outy = []
    for cat in cats:
        # only add outliers if they exist
        if not out[cat].empty:
            for value in out[cat]:
                outx.append(cat)
                outy.append(value) 
                
    # If outliers, shrink whiskers to smallest and largest non-outlier
    qmin = df_gb[vals].min()
    qmax = df_gb[vals].max()
    upper = [min([x,y]) for (x,y) in zip(qmax, upper_cutoff)]
    lower = [max([x,y]) for (x,y) in zip(qmin, lower_cutoff)]

    # Build figure
    p = figure(sizing_mode='stretch_width')
    p.ygrid.grid_line_color = 'white'
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_width = 2
    p.yaxis.axis_label = ylabel
    
    # stems
    p.segment(cats, upper, cats, q3, line_width=2, line_color="black")
    p.segment(cats, lower, cats, q1, line_width=2, line_color="black")

    # boxes
    p.rect(cats, (q3 + q1)/2, 0.5, q3 - q1, fill_color="red", 
           alpha=0.7, line_width=2, line_color="black")

    # median (almost-0 height rects simpler than segments)
    p.rect(cats, q2, 0.5, 0.01, line_color="black", line_width=2)

    # whiskers (almost-0 height rects simpler than segments)
    p.rect(cats, lower, 0.2, 0.01, line_color="black")
    p.rect(cats, upper, 0.2, 0.01, line_color="black")

    # outliers
    p.circle(outx, outy, size=6, color="black")

    return p

p = box_plot(df, 'HP', 'Generation', ylabel='HP')
show(p)

однако, если я изменю параметры в конце, чтобы сказать:

p = box_plot(df, 'Attack', 'Generation', ylabel='HP')
show(p)

приводит к ошибке:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Input In [21], in <cell line: 96>()
     92     p.circle(outx, outy, size=6, color="black")
     94     return p
---> 96 p = box_plot(df, 'Attack', 'Generation', ylabel='HP')
     97 show(p)

Input In [21], in box_plot(df, vals, label, ylabel)
     55 outy = []
     56 for cat in cats:
     57     # only add outliers if they exist
---> 58     if not out[cat].empty:
     59         for value in out[cat]:
     60             outx.append(cat)

File ~\Anaconda3\lib\site-packages\pandas\core\series.py:958, in Series.__getitem__(self, key)
    955     return self._values[key]
    957 elif key_is_scalar:
--> 958     return self._get_value(key)
    960 if is_hashable(key):
    961     # Otherwise index.get_value will raise InvalidIndexError
    962     try:
    963         # For labels that don't resolve as scalars like tuples and frozensets

File ~\Anaconda3\lib\site-packages\pandas\core\series.py:1069, in Series._get_value(self, label, takeable)
   1066     return self._values[label]
   1068 # Similar to Index.get_value, but we do not fall back to positional
-> 1069 loc = self.index.get_loc(label)
   1070 return self.index._get_values_for_loc(self, loc, label)

File ~\Anaconda3\lib\site-packages\pandas\core\indexes\multi.py:2871, in MultiIndex.get_loc(self, key, method)
   2868     return mask
   2870 if not isinstance(key, tuple):
-> 2871     loc = self._get_level_indexer(key, level=0)
   2872     return _maybe_to_slice(loc)
   2874 keylen = len(key)

File ~\Anaconda3\lib\site-packages\pandas\core\indexes\multi.py:3251, in MultiIndex._get_level_indexer(self, key, level, indexer)
   3247     end = level_codes.searchsorted(idx, side="right")
   3249 if start == end:
   3250     # The label is present in self.levels[level] but unused:
-> 3251     raise KeyError(key)
   3252 return slice(start, end)

KeyError: 5

похоже, он работает только со столбцом HP и категорией «Поколение». Другой пример ниже

если я изменю категорию, чтобы сказать «Тип 1», она снова не будет выполнена.

код в конце:

p = box_plot(df, 'HP', 'Type 1', ylabel='HP')
show(p)

приводит к ошибке:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Input In [22], in <cell line: 96>()
     92     p.circle(outx, outy, size=6, color="black")
     94     return p
---> 96 p = box_plot(df, 'HP', 'Type 1', ylabel='HP')
     97 show(p)

Input In [22], in box_plot(df, vals, label, ylabel)
     55 outy = []
     56 for cat in cats:
     57     # only add outliers if they exist
---> 58     if not out[cat].empty:
     59         for value in out[cat]:
     60             outx.append(cat)

File ~\Anaconda3\lib\site-packages\pandas\core\series.py:958, in Series.__getitem__(self, key)
    955     return self._values[key]
    957 elif key_is_scalar:
--> 958     return self._get_value(key)
    960 if is_hashable(key):
    961     # Otherwise index.get_value will raise InvalidIndexError
    962     try:
    963         # For labels that don't resolve as scalars like tuples and frozensets

File ~\Anaconda3\lib\site-packages\pandas\core\series.py:1069, in Series._get_value(self, label, takeable)
   1066     return self._values[label]
   1068 # Similar to Index.get_value, but we do not fall back to positional
-> 1069 loc = self.index.get_loc(label)
   1070 return self.index._get_values_for_loc(self, loc, label)

File ~\Anaconda3\lib\site-packages\pandas\core\indexes\multi.py:2871, in MultiIndex.get_loc(self, key, method)
   2868     return mask
   2870 if not isinstance(key, tuple):
-> 2871     loc = self._get_level_indexer(key, level=0)
   2872     return _maybe_to_slice(loc)
   2874 keylen = len(key)

File ~\Anaconda3\lib\site-packages\pandas\core\indexes\multi.py:3251, in MultiIndex._get_level_indexer(self, key, level, indexer)
   3247     end = level_codes.searchsorted(idx, side="right")
   3249 if start == end:
   3250     # The label is present in self.levels[level] but unused:
-> 3251     raise KeyError(key)
   3252 return slice(start, end)

KeyError: 'Poison'

какие-либо рекомендации, которые помогут мне настроить код, чтобы убедиться, что он работает со всеми возможными комбинациями?

@mosc9575 спасибо за ответ. Итак, как я могу изменить свой код, чтобы убедиться, что он совместим со всеми комбинациями? Я довольно новичок во всем этом, поэтому любая дальнейшая помощь будет принята с благодарностью.

curiouscoder 23.04.2022 14:47
RangeIndex: 800 entries, 0 to 799 # Column Non-Null Count Dtype --- ------ ------- ----- 0 # 800 non-null int64 1 Name 800 non-null object 2 Type 1 800 non-null object 3 Type 2 414 non-null object 4 HP 800 non-null int64 5 Attack 800 non-null int64 6 Defense 800 non-null int64 7 Sp. Atk 800 non-null int64 8 Sp. Def 800 non-null int64 9 Speed 800 non-null int64 10 Generation 800 non-null int64 11 Legendary 800 non-null bool
curiouscoder 24.04.2022 11:58

@mosc9575 mosc9575 из-за использования df.info() выше ни один из столбцов не имеет значения NaN, кроме «Type2», который я не буду использовать. вы упомянули, что проблема заключается в том, что «если не out[cat].empty», «cats = list(df[label].unique())», «out = df_gb.apply(outliers).dropna()», поэтому вместо того, чтобы идти назад и вперед, не могли бы вы сообщить мне, как каждая часть этого кода может быть явно изменена, чтобы обеспечить выполнение кода. как упоминалось ранее, я новичок в этом, и мне все это очень трудно понять

curiouscoder 24.04.2022 12:03

Попробуйте запустить df = df.drop('Type2', axis=1) сразу после df = pd.read_csv(). Но вы должны найти способ отлаживать свой код самостоятельно. Я не буду отлаживать его для вас. SO не является бесплатной службой кодирования. Учебников в сети много.

mosc9575 24.04.2022 17:37

@ mosc9575 Я пробовал это, но, к сожалению, безуспешно (удаление столбца NaN). Я понимаю, что SO не является бесплатной службой кодирования, однако я запрашивал помощь для этой работы, поскольку у меня нет возможности отлаживать проблему, потому что, если бы я это сделал, я бы не спрашивал в первую очередь. Вы пытались помочь мне с этой проблемой, и я благодарен за это, и я не буду просить никакой дополнительной помощи с этой проблемой. по этой конкретной теме на самом деле не так много руководств в Интернете. Я проверил другие форумы, а также YouTube. в любом случае еще раз спасибо

curiouscoder 24.04.2022 18:34
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения текстовых сообщений может быть настолько сложным или простым, насколько вы его сделаете. Как и в любом ML-проекте, вы можете выбрать...
7 лайфхаков для начинающих Python-программистов
7 лайфхаков для начинающих Python-программистов
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
Установка Apache Cassandra на Mac OS
Установка Apache Cassandra на Mac OS
Это краткое руководство по установке Apache Cassandra.
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ...
Создание персонального файлового хранилища
Создание персонального файлового хранилища
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это...
Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
1
5
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы заставить ваш код работать, вы должны применить несколько небольших изменений:

# old
# # Get the categories
# cats = list(df[label].unique())

# # Group Data frame
# df_gb = df.groupby(label)

# Group Data frame
df_gb = df.groupby(label)
# Get the categories
cats = list(df_gb.groups.keys())

Здесь выбранные категории были неправильными. Также измените эту строку:

# old
# if out[cat].empty:
if cat in out and not out[cat].empty: #new

Это связано с тем, что не во всех категориях есть выбросы, и вам нужно как-то их пропустить. Это место, где ваш код выдавал ошибку.

Теперь ваш код показывает пустую цифру, если вы запустите box_plot(df, 'HP', 'Type 1', ylabel='HP'). Это связано с тем, что индекс представляет собой строку, а не число, и bokeh не знает, где разместить поля.

Чтобы сделать это действительным для строк, примените строки к фигуре как x_range при создании figure().

# old
# # Build figure
# p = figure(sizing_mode='stretch_width')

cats = [str(i) for i in cats]
# Build figure
p = figure(sizing_mode='stretch_width', x_range=cats)

Здесь все элементы преобразуются в строку и добавляются к фигуре боке в первую очередь. Таким образом, фигура может правильно добавить коробки.

Все это сделано, вызов p = box_plot(df, 'HP', 'Type 1', ylabel='HP') приводит к этой цифре:

Your output

Большое спасибо за вашу помощь и поддержку в моем вопросе! надеюсь, я смогу использовать это как структуру и применить к различным наборам данных в будущем. Я ценю ваше время и усилия и благодарен за вклад!

curiouscoder 25.04.2022 10:19

Я очень надеюсь, что это поможет вам. Удачи тебе.

mosc9575 25.04.2022 10:30

Другие вопросы по теме