如何将自定义列顺序应用于pandas boxplot?

smc*_*mci 10 python boxplot pandas categorical-data

我可以在pandas DataFrame中获得一个工资列的boxplot ...

train.boxplot(column='Salary', by='Category', sym='')
Run Code Online (Sandbox Code Playgroud)

...但是我无法弄清楚如何定义"类别"列上使用的索引顺序 - 我想根据另一个标准提供我自己的自定义顺序:

category_order_by_mean_salary = train.groupby('Category')['Salary'].mean().order().keys()
Run Code Online (Sandbox Code Playgroud)

如何将自定义列顺序应用于boxplot列?(除了使用前缀强制排序的丑陋的kludging列名)

'Category'是一个带有27个不同值的字符串列:boxplot.所以它可以很容易地分解['Accounting & Finance Jobs','Admin Jobs',...,'Travel Jobs']

在检查时,限制在内部pd.Categorical.from_array(),它转换列对象而不允许排序:

我想我可以破解pandas boxplot()的自定义版本,或者进入对象的内部.并提交增强请求.

编辑:这个问题出现了大熊猫~0.13,并且可能已被最近的(0.19 +?)版本淘汰,根据@ Cireo的最新答案.

Pau*_*l H 8

如果没有一个有效的例子,很难说如何做到这一点.我的第一个猜测是只添加一个包含所需订单的整数列.

一种简单,强力的方法是一次添加一个箱图.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame(np.random.rand(37,4), columns=list('ABCD'))
columns_my_order = ['C', 'A', 'D', 'B']
fig, ax = plt.subplots()
for position, column in enumerate(columns_my_order):
    ax.boxplot(df[column], positions=[position])

ax.set_xticks(range(position+1))
ax.set_xticklabels(columns_my_order)
ax.set_xlim(xmin=-0.5)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Cir*_*reo 5

编辑:这是在版本 0.15-0.18 之间添加直接支持后的正确答案


tl;dr:对于最近的熊猫 - 使用boxplot 的positions参数。

添加一个单独的答案,这可能是另一个问题 - 感谢反馈。

我想在 groupby 中添加自定义列顺序,这给我带来了很多问题。最后,我不得不避免尝试使用boxplotfromgroupby对象,而是自己遍历每个子图以提供明确的位置。

import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame()
df['GroupBy'] = ['g1', 'g2', 'g3', 'g4'] * 6
df['PlotBy'] = [chr(ord('A') + i) for i in xrange(24)]
df['SortBy'] = list(reversed(range(24)))
df['Data'] = [i * 10 for i in xrange(24)]

# Note that this has no effect on the boxplot
df = df.sort_values(['GroupBy', 'SortBy'])
for group, info in df.groupby('GroupBy'):
    print 'Group: %r\n%s\n' % (group, info)

# With the below, cannot use
#  - sort data beforehand (not preserved, can't access in groupby)
#  - categorical (not all present in every chart)
#  - positional (different lengths and sort orders per group)
# df.groupby('GroupBy').boxplot(layout=(1, 5), column=['Data'], by=['PlotBy'])

fig, axes = plt.subplots(1, df.GroupBy.nunique(), sharey=True)
for ax, (g, d) in zip(axes, df.groupby('GroupBy')):
    d.boxplot(column=['Data'], by=['PlotBy'], ax=ax, positions=d.index.values)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在我的最终代码中,确定位置的过程更加复杂,因为每个 sortby 值都有多个数据点,我最终不得不执行以下操作:

to_plot = data.sort_values([sort_col]).groupby(group_col)
for ax, (group, group_data) in zip(axes, to_plot):
    # Use existing sorting
    ordering = enumerate(group_data[sort_col].unique())
    positions = [ind for val, ind in sorted((v, i) for (i, v) in ordering)]
    ax = group_data.boxplot(column=[col], by=[plot_by], ax=ax, positions=positions)
Run Code Online (Sandbox Code Playgroud)

  • 不确定发布问题然后自己回答的礼仪=/ (2认同)