使用 inf Python 将数据分成 bin

Divide data into bins with inf Python

我在 python 中遇到 qcut 函数的问题。我的上限和下限是 -Inf 和 Inf,但是当我使用这些边界应用 qcut 时,Python return 这个错误 "cannot convert float infinity to integer".

朋友告诉我应该把Inf改成1e100(很大的数字代表),这样qcut就可以用了。但是,出现另一个错误:"IndexError: only integers, slices (:), ellipsis (...), numpy.newaxis (None) and integer or boolean arrays are valid indices"

示例:

a1 = [-Inf, 26.6, 36.2, 38.7, 42.1, 47.2, 117.7] 
a2 = [-1e100, 26.6, 36.2, 38.7, 42.1, 47.2, 117.7]

cut_range = [-Inf, 27.0, 33.0, 40.0, Inf] #For a1

cut_range = [-1e+100, 27.0, 33.0, 40.0, 1e+100] #For a2

b = pd.qcut(a, cut_range, duplicates = 'drop')

我想要这样的最终结果:

b = ['[-Inf,27]','(33,40]','(33,40],'(40, Inf]','(40, Inf]','(40, Inf]']
or with 1e100:
b = ['[-1e100,27]','(33,40]','(33,40],'(40, 1e100]','(40, 1e100]','(40, 1e100]']

有人可以帮我解释 Inf 在 Python 和 R 中是如何工作的。它们都是无限的,但它们的行为有何不同。

在 R 中,我尝试使用 Inf 函数并且它起作用了:

as.character(cut(a1,cut_range, include.lowest = TRUE))

你确实需要pd.cut。这是因为您 binning/labeling 您的数据基于范围:

a1 = [-np.inf, 26.6, 36.2, 38.7, 42.1, 47.2, 117.7] 
cut_range = [-np.inf, 27.0, 33.0, 40.0, np.inf]
pd.cut(a1, bins = cut_range, include_lowest=True)
>> [(-inf, 27.0], (-inf, 27.0], (33.0, 40.0], (33.0, 40.0], (40.0, inf], (40.0, inf], (40.0, inf]]

另请注意,qcut 基于 quantiles 标记数据,因此如果您将 [0, 0.25, 0.5, 0.75, 1] 作为 cut_range,则数据将分为 4 个分位数。第一个分位数将属于从最小值到第 25 个百分位数 (0-0.25) 的值。当您添加 -np.inf 时,不能有负百分位值,因此出现错误。

searchsorted

尽管我评论说你需要 pd.cut。我个人使用 searchsorted.

a = np.array([-np.inf, 26.6, 36.2, 38.7, 42.1, 47.2, 117.7])
cut = np.array([27.0, 33.0, 40.0])

labels = np.array([
    f"({x:.1f}, {y:.1f}]"
    for x, y in zip([-np.inf] + list(cut), list(cut) + [np.inf])
])

labels[cut.searchsorted(a)]

array(['(-inf, 27.0]', '(-inf, 27.0]', '(33.0, 40.0]', '(33.0, 40.0]',
       '(40.0, inf]', '(40.0, inf]', '(40.0, inf]'], dtype='<U12')

结果是代码数组 cut.searchsorted(a) 或标签数组,如上所示。它可以被折磨成 pandas.Categorical 类型,但你真的应该只使用 pd.cut.