我在groupby结果上应用qcut,以下是我的问题的简化版本:
a = pd.DataFrame({'A':[1,1,1,1,2,2,2,2],
'B': [0,0,0,0,2,3,7,6]})
a.groupby(['A'])['B'].apply(lambda x: pd.qcut(x, 2))
问题是,该组中的一些引发了ValueError,因为
raise ValueError('Bin edges must be unique: %s' % repr(bins))
ValueError: Bin edges must be unique: array([ 0., 0., 0.])
我想要实现的是,如果qcut失败,跳过(或传递0作为结果)并继续qcut为下一组。 有什么建议吗?
答案 0 :(得分:2)
@ JohnE的回答几乎没有变化,允许我们保留apply
语法。
def try_qcut(x,n):
try:
return pd.qcut(x,n)
except ValueError:
return x*np.nan
a.groupby('A')['B'].apply(lambda x: try_qcut(x, 2))
0 NaN
1 NaN
2 NaN
3 NaN
4 [2, 4.5]
5 [2, 4.5]
6 (4.5, 7]
7 (4.5, 7]
Name: B, dtype: object
答案 1 :(得分:1)
您可以这样做以避免此问题并回答您的问题。但是,我不确定这是否真的是您正在搜索的结果:
a.groupby(['A'])['B'].apply(lambda x: pd.qcut(x, 2) if len(x.unique())>1 else x)
答案 2 :(得分:1)
不紧凑,但我认为这有效吗?
ser = pd.Series()
for i,g in a.groupby('A')['B']:
try:
ser = ser.append(pd.qcut(g,2))
except:
pass
a.join(ser.rename('qcut'))
A B qcut
0 1 0 NaN
1 1 0 NaN
2 1 0 NaN
3 1 0 NaN
4 2 2 [2, 4.5]
5 2 3 [2, 4.5]
6 2 7 (4.5, 7]
7 2 6 (4.5, 7]
如果您更喜欢“0”到“NaN”,请将“pass”替换为:
ser = ser.append( pd.Series( [0]*len(g) ))