首页 > 解决方案 > 如何根据另一列的总和动态离散化熊猫列?

问题描述

我有一个我重复的过程......经常,但不知道如何创建一个动态函数来使这更容易。我需要取一个变量(例如年龄)并将年龄分成至少等于另一列(重量)的 1000 个单位的离散箱。我需要为任何变量动态地执行此操作并控制权重总和。因此,如果我想以 500 单位或 2000 单位为增量进行装箱,我需要将其作为可变参数。

这是一个示例数据集:

import pandas as pd
import numpy as np

age = np.arange(0,30,1)

weight = np.linspace(200, 2500,30)

bin_dict = {'age':age, 'weight':weight}

df = pd.DataFrame(bin_dict)

现在假设我想将年龄放入不少于 1000 个单位的垃圾箱中。结果如下:

df['bin_aged'] = pd.cut(df['age'],
                        bins = [-np.inf, 3, 5, 7, 9, 11,12,13,14,15,16,17,
                                18,19,20,21,22,23,24,25,26,27,28,np.inf],
                        labels = [3, 5, 7, 9, 11,12,13,14,15,16,17,
                                18,19,20,21,22,23,24,25,26,27,28,29])

如果我按新的分箱列分组,这就是它的样子:

df.groupby('bin_aged').agg({'weight':'sum'})

这可能吗?

标签: pythonfunctiondiscretization

解决方案


我想通了……

def dynamic_bin(df, column, weight, minimum):
    """
    

    Parameters
    ----------
    df : dataframe
    column : column to be binned
    weight : column that will dictate the bin
    minimum : minimum weight per bin

    Returns
    -------
    df : dataframe with new binned column

    """
    bins = [-np.inf]
    labels = [] 
    hold_over = []
    for i in sorted(df[column].unique()):
        g = df[df[column] == i].groupby(column).agg({weight:'sum'}).reset_index()
        
        if g[weight].values[0] < minimum:
            if hold_over is None:
                hold_over.append(g[weight].values[0])
                
            elif (sum(hold_over) + g[weight].values[0]) < minimum:
                hold_over.append(g[weight].values[0])
 
                
            elif (sum(hold_over) + g[weight].values[0]) >= minimum:
                hold_over.clear()
                bins.append(g[column].values[0])
                labels.append(g[column].values[0])
                
            
        elif g[weight].values[0] >= minimum:
            bins.append(g[column].values[0])
            labels.append(g[column].values[0])
    
    bins.pop()
    bins.append(np.inf)
    
    
    str_column = str(column)+str("_binned")
    # print(str_column)
    df[str_column] = pd.cut(df[column],
                            bins = bins,
                            labels = labels)
    

    return df

推荐阅读