Python 如何基于变量的另一个值来平均存储该变量?

Python 如何基于变量的另一个值来平均存储该变量?,python,binning,Python,Binning,我的数据汇总了不同区域的作业,按区域的默认交付半径分组,如下所示 radius_km num_jobs 3.0 37745 5.0 327963 6.0 259885 7.0 145021 8.0 128145 9.0 280185 10.0 790295 11.0 72166 12.0 1872242 13.0 1522

我的数据汇总了不同区域的作业,按区域的默认交付半径分组,如下所示

radius_km   num_jobs
3.0          37745
5.0          327963
6.0          259885
7.0          145021
8.0          128145
9.0          280185
10.0         790295
11.0         72166
12.0         1872242
13.0         152221
14.0         202767
15.0         477996
16.0         33438
20.0         17098
我正在尝试将不同的半径组组合在一起,以便现在有X个组(记住半径的连续性,例如3-5km、6-10km),每个组中的作业数总和尽可能接近相等

我一直在尝试使用pd.cut或pd.qcut,但我似乎无法从中得到我想要的东西

我的预期结果如下所示:

radius_km_bin  num_jobs
3.0 - 9.0         x
10.0 - 12.0       y
13.0 - 20         z
其中x~y~z


我在这里选择的范围只是为了说明格式,而不是实际需要的范围。

这里有一个骇人听闻的骇人听闻的方法,我几乎不好意思与大家分享,但它完成了工作(假设你把它分成3个箱子)这是一个简单的优化问题,但因为你本质上是在优化如何分割df,索引是整数,这在python中是不容易的整数编程问题

import pandas as pd
import numpy as np
res=np.empty([0,3]) #empty np array
df = pd.read_csv('test.csv') #read in df
new = pd.DataFrame(columns=['radius_km_bin','num_jobs']) #output df
num_jobs = df.num_jobs.values #assign values to array

for i in range(len(num_jobs)-2): #first split in array
    for j in range(i+1,len(num_jobs)-1): #second split in array
        diff1=abs(sum(num_jobs[:i])-sum(num_jobs[i:j])) #diff between 1st/2nd chunk
        diff2=abs(sum(num_jobs[i:j])-sum(num_jobs[j:])) #diff between 2nd/3rd chunk
        tmp = np.array([[i,j,diff2+diff1]]) #combined error
        res = np.append(res,tmp,axis=0) #save i,j,error to array

i,j = int(res[res[:,2]==min(res[:,2]),0][0]),int(res[res[:,2]==min(res[:,2]),1][0]) #find i,j corresponding to min error, convert to int for indexing

new['radius_km_bin'] = [' '.join([str(kms[0]),'-',str(kms[0:i][-1])]),' '.join([str(kms[i]),'-',str(kms[i:j][-1])]),' '.join([str(kms[j]),'-',str(kms[-1])])] #join kms into string for output dataframe

new['num_jobs'] = [sum(df['num_jobs'][0:i]),sum(df['num_jobs'][i:j]),sum(df['num_jobs'][j:])] #sum num_jobs within the chunks
输出:

  radius_km_bin  num_jobs
0        3 - 10   1969239
1       11 - 12   1944408
2       13 - 20    883520
我相信有更好的方法,但希望这能引导你朝着这个方向前进

编辑-更好的方式:

from scipy.optimize import minimize

def diffs(x):
    diff1=abs(sum(num_jobs[:int(x[0])])-sum(num_jobs[int(x[0]):int(x[1])]))
    diff2=abs(sum(num_jobs[int(x[0]):int(x[1])])-sum(num_jobs[int(x[1]):]))
    diff3=abs(sum(num_jobs[:int(x[0])])-sum(num_jobs[int(x[1]):]))
    return sum([diff1,diff2,diff3])

r = minimize(diffs,x,method='Powell')

i,j = int(r.x[0]),int(r.x[1])
我得到了同样的答案