我有汇总不同区域作业的数据,按区域的默认传送半径分组,因此看起来像这样
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
我在这里选择的范围只是为了说明格式,而不是实际所需的范围。
答案 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])
与此我得到相同的答案