在 geom_density 中使用分类列时出错

Error using categorical column in geom_density

将列转换为分类类型并设置一些美学 属性 (aes()) 以使用它时,出现以下错误:

NotImplementedError: isna is not defined for MultiIndex

例如,这是一个可重现的例子:

randCat = np.random.randint(0,2,500)
randProj = np.random.rand(1,500)
df = pd.DataFrame({'proj': np.ravel(randProj),'cat': np.ravel(randCat)})
df['cat'] = df['cat'].map({0:'firstCat', 1:'secondCat'}) 


df['cat'] = df['cat'].astype('category')
g = ggplot(aes(x='proj', color='cat',fill='cat'), data=df) + geom_density(alpha=0.7)
print(g)

我正在使用 pandas version 0.22.0。 并且 ggplot 0.11.5

有趣的是,当我没有将 "cond" 列设置为 "categorical" 类型(保持为字符串)时,绘图效果很好。但是,出于不同的目的,我需要此列进行分类。

更完整的错误跟踪:

     54     # hack (for now) because MI registers as ndarray
     55     elif isinstance(obj, ABCMultiIndex):
---> 56         raise NotImplementedError("isna is not defined for MultiIndex")
     57     elif isinstance(obj, (ABCSeries, np.ndarray, ABCIndexClass)):
     58         return _isna_ndarraylike(obj)

NotImplementedError: 没有为 MultiIndex 定义 isna

谢谢, 埃亚尔

这可能是导致 ggplot 与 pandas 结合失败的边缘情况。

查看ggplot的源码,在ggploy.py: _construct_plot_data的末尾发现:

groups = [column for _, column in discrete_aes]
if groups:
    return mappers, data.groupby(groups)
else:
    return mappers, [(0, data)]

所以我的猜测是该类别用于 groupby,这导致 pandas 中断。

尝试转换为 object 而不是 category 并且在 geom_density 的情况下删除 fill='cat' 因为这会导致线条和图例被渲染两次:

randCat = np.random.randint(0,2,500)
randProj = np.random.rand(1,500)
df = pd.DataFrame({'proj': np.ravel(randProj),'cat': np.ravel(randCat)})
df['cat'] = df['cat'].map({0:'firstCat', 1:'secondCat'}) 
df['cat'] = df['cat'].astype('object')

g = ggplot(aes(x='proj', color='cat'), data=df) + geom_density(alpha=0.7)
print(g)

另见 http://ggplot.yhathq.com/how-it-works.html and http://ggplot.yhathq.com/docs/geom_density.html

我使用 seaborn 包解决了 "fill" 问题。

import matplotlib.pyplot as plt
import seaborn as sns

sns.kdeplot(df[df['cat'] == 'firstCat']['proj'], shade=True, label='firstCat')
sns.kdeplot(df[df['cat'] == 'secondCat']['proj'], shade=True, label='secondCat')
plt.show()

Plots this