【问题标题】:Pandas histogram (counts) on grouped (by) values分组(按)值的 Pandas 直方图(计数)
【发布时间】:2016-07-27 07:48:43
【问题描述】:

我有一个DataFrame,看起来像这样:

>>> df
    type     value
0      1  0.698791
1      3  0.228529
2      3  0.560907
3      1  0.982690
4      1  0.997881
5      1  0.301664
6      1  0.877495
7      2  0.561545
8      1  0.167920
9      1  0.928918
10     2  0.212339
11     2  0.092313
12     4  0.039266
13     2  0.998929
14     4  0.476712
15     4  0.631202
16     1  0.918277
17     3  0.509352
18     1  0.769203
19     3  0.994378

我想在 type 列上进行分组,并在 10 个新列中获取 value 列的直方图箱,例如类似的东西:

      1  3  9  6  8  10  5  4  7  2
type
1     0  1  0  0  0   2  1  1  0  1
2     2  1  1  0  0   1  1  0  0  0
3     2  0  0  0  0   1  1  0  0  0
4     1  1  0  0  0   1  0  0  0  1

1 列是第一个 bin 的计数(0.00.1)等等...

使用numpy.histogram,我只能得到以下内容:

>>> df.groupby('type')['value'].agg(lambda x: numpy.histogram(x, bins=10, range=(0, 1)))
    type
1       ([0, 1, 1, 1, 1, 0, 0, 0, 0, 2], [0.0, 0.1, 0....
2       ([2, 0, 1, 0, 1, 0, 0, 0, 1, 1], [0.0, 0.1, 0....
3       ([2, 0, 0, 0, 1, 0, 0, 0, 0, 1], [0.0, 0.1, 0....
4       ([1, 1, 1, 0, 0, 0, 0, 0, 0, 1], [0.0, 0.1, 0....
Name: value, dtype: object

之后我没有设法输入正确的格式(至少不是以简单的方式)。

我找到了一个可以做我想做的事的技巧,但它很丑:

>>> d = {str(k): lambda x, _k = k: ((x >= (_k - 1)/10) & (x < _k/10)).sum() for k in range(1, 11)}
>>> df.groupby('type')['value'].agg(d)
      1  3  9  6  8  10  5  4  7  2
type
1     0  1  0  0  0   2  1  1  0  1
2     2  1  1  0  0   1  1  0  0  0
3     2  0  0  0  0   1  1  0  0  0
4     1  1  0  0  0   1  0  0  0  1

有没有更好的方法来做我想做的事?我知道在R 中,aggregate 方法可以返回一个DataFrame,但在python 中却不行...

【问题讨论】:

    标签: python pandas aggregate histogram


    【解决方案1】:

    这就是你想要的吗?

    In [98]: %paste
    bins = np.linspace(0, 1.0, 11)
    labels = list(range(1,11))
    
    (df.assign(q=pd.cut(df.value, bins=bins, labels=labels, right=False))
       .pivot_table(index='type', columns='q', aggfunc='size', fill_value=0)
    )
    ## -- End pasted text --
    Out[98]:
    q     1   2   3   4   5   6   7   8   9   10
    type
    1      0   1   0   1   0   0   1   1   1   4
    2      1   0   1   0   0   1   0   0   0   1
    3      0   0   1   0   0   2   0   0   0   1
    4      1   0   0   0   1   0   1   0   0   0
    

    【讨论】:

    • 它可以解决问题 - 我没有DataFrame.assign,我会看看我是否可以更新我的pandas 版本(我可能无法...)。如果我想在两列上分组,是否可以使用它,例如typeversion?
    • @Holt,我使用.assign() 使其成为单行,您可以先添加此列,然后将其用作第二个命令。对于version - 我认为您应该在问题中更新您的样本和预期的 DF,因为它不是很清楚
    • 我设法通过使用df['bin'] = pd.cut(...) 让它工作。我担心.pivot_table 可能不适用于两个索引,但它确实可以(index=('col1', 'col2')),而且我将不得不删除很多列(我的真实数据框有很多列)但显然drop 是没有必要让它工作。我还添加了从1.01.1 的额外垃圾箱,以便在value == 1 时获得一个特定的垃圾箱(但我在我的问题中忘记了这一点,所以你无法猜到......)。谢谢。
    • 还有一个小细节:为了正确模仿numpy.histogram,在对pandas.cut的调用中,right参数应该设置为False(默认情况下numpy.histogram会被保留) -inclusive ([a, b)) 而pandas.cut bins 默认为右包含 ((a, b])。
    • @Holt,另一个好点,谢谢! :) 我已经更新了答案
    猜你喜欢
    • 2017-05-28
    • 2018-02-03
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    • 2021-11-02
    • 1970-01-01
    • 2013-11-04
    • 2015-10-28
    相关资源
    最近更新 更多