如何根据该变量的另一个值来对一个变量进行均等化?

时间:2019-08-19 22:38:46

标签: 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         152221
14.0         202767
15.0         477996
16.0         33438
20.0         17098

我正在尝试将不同的半径组合并在一起,以便现在有X个组(记住半径连续性,例如3-5km,6-10km),每个组中的num_jobs总数尽可能接近。

我一直在尝试使用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

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

1 个答案:

答案 0 :(得分:1)

这是一种让我几乎感到羞耻的骇人听闻的方法,但是可以完成工作(假设您将它分成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])

与此我得到相同的答案