如何将 Pandas 系列的 bin 大小设置为每个 bin 的预设值 max/min

How can I bin a Pandas Series setting the bin size to a preset value of max/min for each bin

我有一个 pd.Series 的浮点数,我想将它放入 n 个箱子 中,每个箱子的箱子大小设置为 max/min是预设值(例如1.20)?

该要求意味着 bin 的大小不是恒定的。例如:

data = pd.Series(np.arange(1, 11.0))
print(data)

0     1.0
1     2.0
2     3.0
3     4.0
4     5.0
5     6.0
6     7.0
7     8.0
8     9.0
9    10.0
dtype: float64

我希望 bin 大小为:

1.00 <= bin 1 < 1.20
1.20 <= bin 2 < 1.20 x 1.20 = 1.44
1.44 <= bin 3 < 1.44 x 1.20 = 1.73
...

等等

谢谢

这是一个 pd.cut, where the bins can be computed taking the np.cumprod 的数组,其中填充了 1.2:

data = pd.Series(list(range(11)))
import numpy as np

n = 20 # set accordingly
bins= np.r_[0,np.cumprod(np.full(n, 1.2))]
# array([ 0.        ,  1.2       ,  1.44      ,  1.728 ...
pd.cut(data, bins)

0                 NaN
1          (0.0, 1.2]
2      (1.728, 2.074]
3      (2.986, 3.583]
4        (3.583, 4.3]
5         (4.3, 5.16]
6       (5.16, 6.192]
7       (6.192, 7.43]
8       (7.43, 8.916]
9     (8.916, 10.699]
10    (8.916, 10.699]
dtype: category

在这种情况下,bins 上升到:

np.r_[0,np.cumprod(np.full(20, 1.2))]

array([ 0.        ,  1.2       ,  1.44      ,  1.728     ,  2.0736    ,
        2.48832   ,  2.985984  ,  3.5831808 ,  4.29981696,  5.15978035,
        6.19173642,  7.43008371,  8.91610045, 10.69932054, 12.83918465,
       15.40702157, 18.48842589, 22.18611107, 26.62333328, 31.94799994,
       38.33759992])

所以你要根据实际数据的取值范围来设置

我认为这是最好的方法,因为您正在考虑数组中的 maxmin 值。因此,您无需担心您使用的是什么值,只需为您的垃圾箱使用 乘数 或 step_size (当然您需要添加列名或如果您将使用 DataFrame,请提供一些附加信息):

data = pd.Series(np.arange(1, 11.0))
bins = []
i = min(data)
while i < max(data):
    bins.append(i)
    i = i*1.2
    bins.append(i)
bins = list(set(bins))
bins.sort()
df = pd.cut(data,bins,include_lowest=True)
print(df)

输出:

0       (0.999, 1.2]
1     (1.728, 2.074]
2     (2.986, 3.583]
3       (3.583, 4.3]
4        (4.3, 5.16]
5      (5.16, 6.192]
6      (6.192, 7.43]
7      (7.43, 8.916]
8    (8.916, 10.699]
9    (8.916, 10.699]

Bins 输出:

Categories (13, interval[float64]): [(0.999, 1.2] < (1.2, 1.44] < (1.44, 1.728] < (1.728, 2.074] < ... <
                                     (5.16, 6.192] < (6.192, 7.43] < (7.43, 8.916] <
                                     (8.916, 10.699]]

感谢大家提出的所有建议。 None 完全符合我的要求(可能是因为我最初的问题不够清楚)但他们确实帮助我弄清楚该怎么做所以我决定 post 我自己的答案(我希望这个这是我应该做的,因为我在成为 Whosebug 的活跃成员方面相对较新...)

我最喜欢@yatu 的矢量化建议,因为它可以更好地扩展大型数据集,但我正在寻找不仅可以自动计算 bin 还可以计算出覆盖数据集所需的最小 bin 数量的方法。

这是我提出的算法:

  1. bin 大小被定义为 bin_max_i/bin_min_i 是常量:
bin_max_i / bin_min_i = bin_ratio
  1. 计算出所需 bin 大小 (bin_ratio) 的 bin 数量:
data_ratio = data_max / data_min
n_bins = math.ceil( math.log(data_ratio) / math.log(bin_ratio) )
  1. 设置最小 bin 的下边界,使最小的数据点适合它:
bin_min_0 = data_min
  1. 创建n个满足条件的非重叠bin:
bin_min_i+1 = bin_max_i
bin_max_i+1 = bin_min_i+1 * bin_ratio
  1. 一旦可以在已创建的 bin 之间拆分所有数据集,就停止创建更多的 bin。也就是说,停止一次:
bin_max_last > data_max

这是一个代码片段:

import math
import pandas as pd

bin_ratio = 1.20

data = pd.Series(np.arange(2,12))
data_ratio = max(data) / min(data)

n_bins = math.ceil( math.log(data_ratio) / math.log(bin_ratio) )
n_bins = n_bins + 1               # bin ranges are defined as [min, max)

bins = np.full(n_bins, bin_ratio) # initialise the ratios for the bins limits
bins[0] = bin_min_0               # initialise the lower limit for the 1st bin
bins = np.cumprod(bins)           # generate bins

print(bins)
[ 2.          2.4         2.88        3.456       4.1472      4.97664
  5.971968    7.1663616   8.59963392 10.3195607  12.38347284]

我现在准备构建数据直方图:

data.hist(bins=bins)