具有预定义仓位和关闭/打开间隔的仓位变量

时间:2019-07-24 22:38:49

标签: python pandas numpy binning

我有一组垃圾箱,可以通过以下方式定义:

  1. 每个bin的一组非重叠边界元组:

    间隔:[(0,1),(1,2),(3,4)]

  2. 一组标识每个元组的哪个边界闭合的指示器:

    Closed_Boundaries:['正确','正确','都']

  3. 每个间隔的一组标签

    标签:['第一','第二','第三']

我正在寻找一种有效,优雅且可扩展的方法,将该分箱方法应用于熊猫数据框中的数字序列,以使结果包括分箱逻辑所标识的各个标签:

数据输入:[3.5、1、0.5、3]

数据结果:[“第三”,“第一”,“第一”,“第三”]

我尝试使用pandas.IntervalIndex.from_tuples(),然后使用pandas.cut()。但是,使用IntervalIndex.from_tuples()时,pandas.cut()的labels参数被禁用,而后者的name参数不允许我设置将标签用作替换值。

PS:IntervalIndex不支持带有标签的熊猫问题已经here进行了讨论。

1 个答案:

答案 0 :(得分:1)

如果所有间隔都在同一侧闭合

最简单的方法是使用pd.cut。但是,有一个outstanding buglabelsbins时会忽略IntervalIndex

def cut(array, bins, labels, closed='right'):
    _bins = pd.IntervalIndex.from_tuples(bins, closed=closed)

    x = pd.cut(array, _bins)
    x.categories = labels # workaround for the bug
    return x

array = [3.5, 1, 0.5, 3]
bins = [(0,1), (1,2), (3,4)]
labels = ['first', 'second', 'third']

df = pd.DataFrame({
    'value': array,
    'category': cut(array, bins, labels, closed='right')
})

输出:

   value category
0    3.5    third
1    1.0    first
2    0.5    first
3    3.0      NaN

如果每个间隔都不一样

事情变得很慢,因为代码不是矢量化的,但是从概念上讲很简单:对于数组中的每个项目,找到它所属的第一个容器并添加该容器的标签。

def cut(array, bins, labels):
    intervals = [pd.Interval(*b) for b in bins]

    categories = []
    for value in array:
        cat = None
        for i, interval in enumerate(intervals):
            if value in interval:
                cat = labels[i]
                break
        categories.append(cat)

    return categories

cut([3.5, 1, 0.5, 3], bins=[(0,1,'right'),(1,2,'right'),(3,4,'left')], labels=['first', 'second', 'third'])

我修改了bin元组以包括封闭它们的哪一侧。选项为leftrightbothneither