Pandas 如果失败,是否为下一个分组继续qcut?

Pandas 如果失败,是否为下一个分组继续qcut?,pandas,Pandas,我对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(bi

我对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。
有什么建议吗?

您可以这样做以避免问题并回答您的问题。但是,我不确定这是否真的是您要搜索的结果:

a.groupby(['A'])['B'].apply(lambda x: pd.qcut(x, 2) if len(x.unique())>1 else x)

不是很紧凑,但我觉得这样行吗

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”,请将“通过”替换为:


@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

这还不完全正确,因为示例数据帧在第一个组中包含所有零,
x*np.nan
也有效,
len(x.unique())>1
是qcut的一个必要条件,但不是充分条件,如果只有Python有一行try/except语法,它仍然会失败,
pd.qcut([0,0,1],2)
!美好的我会留下我的答案来保存+1,但这样更好。不,你的答案也很好,我喜欢你这样使用
join
来填充空值。也许你可以用
ser=ser.append(pd.qcut(g,2))
(这只是我个人的喜好),你最好添加
.astype(str)
,否则它不能用于多个不失败的组耶,好的一点,append更干净。但是
qcut
似乎已经返回了一个字符串,所以我不知道是否需要
astype(str)
?我玩了一些例子,看不出有什么不同。@JohnE也许这只是最新的版本,但对我来说
pd.qcut(pd.Series([1,2,3,4]),2.append(pd.qcut(pd.Series([0,1,2,3])
引发
ValueError:categorical concat中不兼容的类别
似乎qcut中的类别信息一旦与a连接就丢失了,那不是撞车,这是你想要的,对吧?它只会为没有崩溃的组填充qcut结果。如果您喜欢用“0”而不是“NaN”来填充,请参阅我添加的注释,或者您可以用
fillna(0)
来修复。
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