0

我正在亿万富翁特征数据库数据集上练习我的 ML 分类技能。

sframe用于加载和操作数据以及seaborn用于可视化。

在数据分析的过程中,我想绘制一个按类别变量分组的箱线图,就像seaborn教程中的这个: 按分类值分组的箱线图

在数据集中,有一个networthusbillion数值变量和selfmade分类变量来说明亿万富翁是否有钱self-made或他是否inherited有钱。

当我尝试使用 绘制类似的箱线图sns.boxplot(x='selfmade', y='networthusbillion', data=data)时,会引发以下错误:

---------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-17-f4bd651c2ae7> in <module>()
----> 1 sns.boxplot(x='selfmade', y='networthusbillion', data=billionaires)

/home/iulian/.virtualenvs/data-science-python2/lib/python2.7/site-packages/seaborn/categorical.pyc in boxplot(x, y, hue, data, order, hue_order, orient, color, palette, saturation, width, fliersize, linewidth, whis, notch, ax, **kwargs)
   2127     plotter = _BoxPlotter(x, y, hue, data, order, hue_order,
   2128                           orient, color, palette, saturation,
-> 2129                           width, fliersize, linewidth)
   2130 
   2131     if ax is None:

/home/iulian/.virtualenvs/data-science-python2/lib/python2.7/site-packages/seaborn/categorical.pyc in __init__(self, x, y, hue, data, order, hue_order, orient, color, palette, saturation, width, fliersize, linewidth)
    420                  width, fliersize, linewidth):
    421 
--> 422         self.establish_variables(x, y, hue, data, orient, order, hue_order)
    423         self.establish_colors(color, palette, saturation)
    424 

/home/iulian/.virtualenvs/data-science-python2/lib/python2.7/site-packages/seaborn/categorical.pyc in establish_variables(self, x, y, hue, data, orient, order, hue_order, units)
    136             # See if we need to get variables from `data`
    137             if data is not None:
--> 138                 x = data.get(x, x)
    139                 y = data.get(y, y)
    140                 hue = data.get(hue, hue)

AttributeError: 'SFrame' object has no attribute 'get'

我尝试了以下表格来绘制箱线图 - 它们都没有达到结果:

sns.boxplot(x=billionaires['selfmade'], y=billionaires['networthusbillion'])
sns.boxplot(x='selfmade', y='networthusbillion', data=billionaires['selfmade', 'networthusbillion'])

但是,我可以使用 绘制箱线图sframe,但不按以下方式分组selfmade

sns.boxplot(x=billionaires['networthusbillion'])

所以,我的问题是:有没有办法使用 ? 绘制按分类变量分组的箱形图sframe?也许我做错了什么?

顺便说一句,我设法pandas.DataFrame使用相同的语法 ( sns.boxplot(x='selfmade', y='networthusbillion', data=data)) 来绘制它,所以使用sframewith进行分组可能seaborn还没有实现。

4

2 回答 2

0

问题是sns.boxplot期望数据具有get像熊猫数据框这样的方法。在 Pandas 中,该get方法返回单个列,因此它与括号索引相同,即your_df['your_column_name'].

解决此问题的最简单方法是调用to_dataframesframe 上的方法将其转换为数据帧。

sns.boxplot(x='selfmade', y='networthusbillion', data=data.to_dataframe())

或者,您可以通过编写类包装器或在 SFrame 类上使用猴子补丁来解决问题。 get

import numpy as np
import sframe
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# For demostration purposes
def to_sframe(df):
    import sframe
    d = {}
    for key in df.keys():
        d[key] = list(df[key])
    return sframe.SFrame(d)
pd.DataFrame.to_sframe = to_sframe

tips = sns.load_dataset('tips')

# Monkey patch sframe's get and _CategoricalPlotter's _group_longform
def get(self, *args):
    key = args[0]
    return self.__getitem__(key) if key else None
sframe.SFrame.get = get


def _group_longform(self, vals, grouper, order):
    """Group a long-form variable by another with correct order."""
    #import pdb;pdb.set_trace()

    if type(vals) == sframe.SArray:
        _sf = sframe.SFrame({'vals':vals, 'grouper':grouper})
        grouped_vals = _sf.groupby('grouper', sframe.aggregate.CONCAT('vals'))
        out_data = []
        for g in order:
            try:
                g_vals = np.asarray(grouped_vals.filter_by(g, 'grouper')["List of vals"][0])
            except KeyError:
                g_vals = np.array([])
            out_data.append(g_vals)
        label = ""
        return out_data, label

    ## Code copied from original _group_longform
    # Ensure that the groupby will work
    if not isinstance(vals, pd.Series):
        vals = pd.Series(vals)

    # Group the val data
    grouped_vals = vals.groupby(grouper)
    out_data = []
    for g in order:
        try:
            g_vals = np.asarray(grouped_vals.get_group(g))
        except KeyError:
            g_vals = np.array([])
        out_data.append(g_vals)

    # Get the vals axis label
    label = vals.name

    return out_data, label

sns.categorical._CategoricalPlotter._group_longform = _group_longform


# Plots should be equivalent
#1.
plt.figure()
sns.boxplot(x="day", y="total_bill", data=tips)
#2.
plt.figure()
sns.boxplot(x="day", y="total_bill", data=tips.to_sframe(),
            order=["Thur", "Fri", "Sat", "Sun"])
plt.xlabel("day")
plt.ylabel("total_bill")

plt.show()
于 2016-04-08T02:41:03.400 回答
0

TL;博士

使用sframewithseaborn进行分组尚未实现。


在深入研究 seaborn 的源代码后,我发现它是专门为与pandas.DataFrame. 在他们的回答中采用 absoluteNoWarranty 的建议,我收到以下错误:

TypeError: __getitem__() takes exactly 2 arguments (3 given)

看一下on callargs的函数,有这样的数据:get

('gender', 'gender')

发生这种情况是因为源代码中的以下代码BoxPlot

# See if we need to get variables from `data`
if data is not None:
    x = data.get(x, x)
    y = data.get(y, y)
    hue = data.get(hue, hue)
    units = data.get(units, units)

它尝试获取该值并使用与备用值相同的值,以防万一它不存在。这会导致 中的错误__getitem__(),因为它是使用(self, 'gender', 'gender')参数调用的。

我试图重写get()函数如下:

def get(self, *args):
    return self.__getitem__(args[0]) if args[0] else None  # The `None` is here because the `units` in the source code is `None` for boxplots.

在这里我得到了结束我尝试的错误:

TypeError: 'SArray' object is not callable

查看源代码,它检查y数据是否为a pd.Series,如果不是,则将y值转换为1:

if not isinstance(vals, pd.Series):
    vals = pd.Series(vals)

# Group the val data
grouped_vals = vals.groupby(grouper)

当执行vals.groupby(grouper)(grouper 仍然是一个SArray实例)时,它会进入 pandas 核心工作,在那里SArray调用并抛出错误。故事结局。

于 2016-04-08T17:28:52.863 回答