装箱后无法访问数据框的 groupby 对象的各个列
Posted
技术标签:
【中文标题】装箱后无法访问数据框的 groupby 对象的各个列【英文标题】:Cannot access individual columns of a groupby object of a dataframe after binning it 【发布时间】:2019-01-21 22:23:03 【问题描述】:这个问题与this one 类似,但有一个关键区别 - 链接问题的解决方案不能解决数据框分组到 bin 时的问题。
以下用于箱线图绘制 2 个变量的 bin 的相对分布的代码会产生错误:
import pandas as pd
import seaborn as sns
raw_data = 'regiment': ['Nighthawks', 'Nighthawks', 'Nighthawks', 'Nighthawks', 'Dragoons', 'Dragoons', 'Dragoons', 'Dragoons', 'Scouts', 'Scouts', 'Scouts', 'Scouts'],
'company': ['1st', '1st', '2nd', '2nd', '1st', '1st', '2nd', '2nd','1st', '1st', '2nd', '2nd'],
'name': ['Miller', 'Jacobson', 'Ali', 'Milner', 'Cooze', 'Jacon', 'Ryaner', 'Sone', 'Sloan', 'Piger', 'Riani', 'Ali'],
'preTestScore': [4, 24, 31, 2, 3, 4, 24, 31, 2, 3, 2, 3],
'postTestScore': [25, 94, 57, 62, 70, 25, 94, 57, 62, 70, 62, 70]
df = pd.DataFrame(raw_data, columns = ['regiment', 'company', 'name', 'preTestScore', 'postTestScore'])
df1 = df.groupby(['regiment'])['preTestScore'].value_counts().unstack()
df1.fillna(0, inplace=True)
sns.boxplot(x='regiment', y='preTestScore', data=df1)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-241-fc8036eb7d0b> in <module>()
----> 1 sns.boxplot(x='regiment', y='preTestScore', data=df1)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\seaborn\categorical.py in boxplot(x, y, hue, data, order, hue_order, orient, color, palette, saturation, width, dodge, fliersize, linewidth, whis, notch, ax, **kwargs)
2209 plotter = _BoxPlotter(x, y, hue, data, order, hue_order,
2210 orient, color, palette, saturation,
-> 2211 width, dodge, fliersize, linewidth)
2212
2213 if ax is None:
~\AppData\Local\Continuum\anaconda3\lib\site-packages\seaborn\categorical.py in __init__(self, x, y, hue, data, order, hue_order, orient, color, palette, saturation, width, dodge, fliersize, linewidth)
439 width, dodge, fliersize, linewidth):
440
--> 441 self.establish_variables(x, y, hue, data, orient, order, hue_order)
442 self.establish_colors(color, palette, saturation)
443
~\AppData\Local\Continuum\anaconda3\lib\site-packages\seaborn\categorical.py in establish_variables(self, x, y, hue, data, orient, order, hue_order, units)
149 if isinstance(input, string_types):
150 err = "Could not interpret input ''".format(input)
--> 151 raise ValueError(err)
152
153 # Figure out the plotting orientation
ValueError: Could not interpret input 'regiment'
如果我删除 x
和 y
参数,它会生成一个箱线图,但它不是我想要的:
我该如何解决这个问题?我尝试了以下方法:
df1 = df.groupby(['regiment'])['preTestScore'].value_counts().unstack()
df1.fillna(0, inplace=True)
df1 = df1.reset_index()
df1
它现在看起来像一个数据框,所以我想提取这个数据框的列名并按顺序为每个列绘制:
cols = df1.columns[1:len(df1.columns)]
for i in range(len(cols)):
sns.boxplot(x='regiment', y=cols[i], data=df1)
这看起来不对。事实上,这不是一个正常的数据帧;如果我们打印出它的列,它不会将 regiment
显示为列,这就是 boxplot 给出错误 ValueError: Could not interpret input 'regiment'
的原因:
df1.columns
>>> Index(['regiment', 2, 3, 4, 24, 31], dtype='object', name='preTestScore')
所以,如果我能以某种方式使regiment
成为数据框的一列,我想我应该能够绘制preTestScore
与regiment
的箱线图。我错了吗?
编辑:我想要的是这样的:
df1 = df.groupby(['regiment'])['preTestScore'].value_counts().unstack()
df1.fillna(0, inplace=True)
# This df2 dataframe is the one I'm trying to construct using groupby
data = 'regiment':['Dragoons', 'Nighthawks', 'Scouts'], 'preTestScore 2':[0.0, 1.0, 2.0], 'preTestScore 3':[1.0, 0.0, 2.0],
'preTestScore 4':[1.0, 1.0, 0.0], 'preTestScore 24':[1.0, 1.0, 0.0], 'preTestScore 31':[1.0, 1.0, 0.0]
cols = ['regiment', 'preTestScore 2', 'preTestScore 3', 'preTestScore 4', 'preTestScore 24', 'preTestScore 31']
df2 = pd.DataFrame(data, columns=cols)
df2
fig = plt.figure(figsize=(20,3))
count = 1
for col in cols[1:]:
plt.subplot(1, len(cols)-1, count)
sns.boxplot(x='regiment', y=col, data=df2)
count+=1
【问题讨论】:
value_counts
将计算唯一值的数量(在这种情况下,每个组的唯一 preTestScores 的数量)。您希望箱线图最终看起来如何?
sns.boxplot
自己分组数据,如果你只做sns.boxplot(x='regiment', y='preTestScore', data=df)
,会不会是想要的结果?
@Teoretic 我已经编辑了问题以显示我在寻找什么。
【参考方案1】:
如果你对你的数据框df1
执行reset_index()
,你应该得到你想要的数据框。
问题是您有一个所需的列 (regiment
) 作为索引,因此您需要重置它并使其成为另一列。
编辑:添加add_prefix
以获得结果数据框中的正确列名
示例代码:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
raw_data = 'regiment': ['Nighthawks', 'Nighthawks', 'Nighthawks', 'Nighthawks', 'Dragoons', 'Dragoons', 'Dragoons', 'Dragoons', 'Scouts', 'Scouts', 'Scouts', 'Scouts'],
'company': ['1st', '1st', '2nd', '2nd', '1st', '1st', '2nd', '2nd','1st', '1st', '2nd', '2nd'],
'name': ['Miller', 'Jacobson', 'Ali', 'Milner', 'Cooze', 'Jacon', 'Ryaner', 'Sone', 'Sloan', 'Piger', 'Riani', 'Ali'],
'preTestScore': [4, 24, 31, 2, 3, 4, 24, 31, 2, 3, 2, 3],
'postTestScore': [25, 94, 57, 62, 70, 25, 94, 57, 62, 70, 62, 70]
df = pd.DataFrame(raw_data, columns = ['regiment', 'company', 'name', 'preTestScore', 'postTestScore'])
df1 = df.groupby(['regiment'])['preTestScore'].value_counts().unstack()
df1.fillna(0, inplace=True)
df1 = df1.add_prefix('preTestScore ') # <- add_prefix for proper column names
df2 = df1.reset_index() # <- Here is reset_index()
cols = df2.columns
fig = plt.figure(figsize=(20,3))
count = 1
for col in cols[1:]:
plt.subplot(1, len(cols)-1, count)
sns.boxplot(x='regiment', y=col, data=df2)
count+=1
输出:
【讨论】:
我已经这样做了reset_index()
,我在问题中提到了它。在那之后的代码没有工作。
@Kristada673 如果您尝试复制粘贴并执行我的代码,它会不会产生与 我想要的是类似这样的东西部分相同的输出?跨度>
@Kristada673 好吧,它没有在列名中设置“preTestScore”后缀,您要添加这些后缀吗? (比如将列“2”命名为“preTestScore 2”)?
是的,确实如此。是的,将主列名称附加到 y 值会很好。以上是关于装箱后无法访问数据框的 groupby 对象的各个列的主要内容,如果未能解决你的问题,请参考以下文章
添加 groupby 对象的单个数据框的数字列的 Pythonic 方法