需求背景
有两张表,A表记录了很多款产品的三个基础字段,分别是产品ID,地区代码和重量:
B表是运费明细表,这个表结构很“业务”。每行对应着单个地区,不同档位重量,所对应的运费:
比如121地区,0-0.5kg的产品,运费是5.38元;2.01(实际应该是大于1)-3kg,运费则是5.44元。
现在,我们想要结合A表和B表,统计出A表每个产品付多少运费,应该怎么实现?
可以先自己思考一分钟图片
解题思路
人海战术
A表一共215行,我们只需要找215个人,每个人只需要记好自己要统计那款产品的地区代码和重量字段,然后在B表中根据地区代码,找到所在地区运费标准,然后一眼扫过去,就能得到最终运费了。
两个“只需要”,问题就这样easy的解决了。
问题变成了,我还差214个人。
解构战术
通过人海战术,我们其实已经明确了解题的朴素思路:根据地区代码和重量,和B表匹配,返回运费结果。
难点在于,B表是偏透视表结构的,运费是横向分布,用Pandas就算用地区代码匹配,还是不能找到合适的运费区间。
怎么办呢?
如果我们把B表解构,变成“源数据”格式,问题就全部解决了:
转换完成后,和A表根据地区代码做一个匹配筛选,答案就自己跑出来了。
下面是动手时刻。
具体实现
先导入数据,A表(product):
B表(cost):
要想把B表变成“源数据”的格式,关键在于理解stack()堆叠操作,结合示例图比较容易搞懂:
通过stack操作,把多列变为单列多行,原本的2列数据堆成了1列,从而方便了一些场景下的匹配。要变回来也很简单,unstack即可:
在我们的具体场景中,先指定好不变的索引列,然后直接上stack:
这样,就得到了我们目标的源数据。接着,A表和B表做匹配:
值得注意的是,因为我们根据每个地方的重量区间做了堆叠,这里的匹配结果,每个产品保留了对应地区,所有重量区间的价格,离最终结果还有一步之遥。
需要把重量区间做拆分,从而和产品重量对比,找到对应的重量区间:
接着,根据重量的最低、最高区间,判断每一行的重量是否符合区间:
最后,筛选出符合区间的产品,及对应的价格等字段:
数据源
地区代码地区缩写0~0.50.501~11.01~22.01~33.01~44.01~55.01~77.01~1010.01~1515.01~100000121AS5.38 5.38 5.38 5.445.535.585.586.096.16.24122BW6.70 6.80 7.13 7.497.858.219.0510.0411.6913.96123Gos7.21 7.34 7.68 8.098.468.889.810.8812.6515.11124Wol7.21 7.34 7.68 8.098.468.889.810.8812.6515.11125New7.21 7.34 7.68 8.098.468.889.810.8812.6515.11126Can7.21 7.34 7.68 8.098.468.889.810.8812.6515.11127Alb7.21 7.31 7.65 8.058.468.869.7610.8412.6115.09128Twe7.21 7.23 7.64 8.048.448.849.7510.8312.6115.09129NSW8.93 9.71 10.85 12.0113.1614.416.7120.192634.2130Mel6.75 8.04 8.51 8.99.419.9510.941214.0817.13131Mlo7.14 8.43 8.86 9.349.8510.3511.4512.6614.7317.93132Gee7.69 10.83 11.49 12.2512.9913.7415.3917.2520.3825.28133Bal7.69 12.36 13.29 14.2815.2916.2818.4520.9525.2331.86134Wod7.69 9.75 10.39 11.0811.812.5114.0815.8418.8523.54135VIC8.74 14.59 15.74 16.9818.1819.4621.7324.8830.1438.41136Bri6.83 7.94 8.38 8.869.419.9911.0312.1514.117.1137BTT7.36 8.34 8.83 9.349.910.4111.6112.9415.2118.74138Ips7.93 10.91 11.84 12.8413.8614.8317.0419.6323.9830.79139Gol7.93 9.30 10.20 11.1312.0913.0815.0817.5321.6528.14140Coo7.93 9.59 10.26 11.0111.7612.5514.2316.1319.424.55141Sun7.93 10.86 11.84 12.8613.8814.8317.0419.6323.9930.8142QA9.04 13.84 15.31 16.8118.319.8422.6426.4432.9143.01143QLD9.04 14.50 16.70 18.8921.1323.427.5633.3343.2658.7144LDQ9.04 14.81 17.30 19.8122.3324.9129.7136.2347.5565.23145Ade7.15 8.40 9.04 9.6610.2810.9612.3914.0816.9421.43146AD7.36 8.44 9.05 9.710.3411.0312.4914.1517.0621.55147SA 9.04 14.20 16.13 18.0319.9921.9625.6830.6939.4159.41148Per7.31 10.50 11.95 13.4514.9416.4519.2523.129.6939.99149Pe7.51 10.79 12.25 13.8115.3316.8519.7523.6630.4340.96150WA 9.04 16.25 20.23 24.2528.3532.540.3151.0369.598.51151WAE9.04 16.39 20.49 24.6428.8633.1841.1652.1971.26101.09152Tas7.30 10.23 11.33 12.4613.6614.8517.0420.0525.2433.31153TWB8.41 11.48 12.70 13.9515.316.6319.0922.4928.337.35154NTA9.04 16.34 20.39 24.4928.6632.940.8851.7970.66100.2155NTB9.04 16.34 20.39 24.4928.6632.940.8851.7970.66100.2156Nor7.75 12.73 14.96 17.1919.4321.6625.931.6841.7157.31157Chr7.75 14.43 17.35 20.3123.2626.2131.8139.4852.7673.41158Aus7.75 11.81 13.11 14.4415.7417.0419.5422.9428.8137.98