Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 日本的SUMIFS公式_Python_Pandas_Data Analysis - Fatal编程技术网

Python 日本的SUMIFS公式

Python 日本的SUMIFS公式,python,pandas,data-analysis,Python,Pandas,Data Analysis,我在一家物流公司工作,我们为客户提供B2C服务。因此,我们有一张表格形式的费率卡,以及交付/交易清单、包裹重量和交付地点 我已经看到很多SUMIFS的问题在这里得到了回答,但与我需要的问题大不相同 第一个事务数据框包含事务id,权重,孤岛,类别 transaction weight island category 1 0.3 luzon regular 2 0.5 visayas express 3

我在一家物流公司工作,我们为客户提供B2C服务。因此,我们有一张表格形式的费率卡,以及交付/交易清单、包裹重量和交付地点

我已经看到很多SUMIFS的问题在这里得到了回答,但与我需要的问题大不相同

第一个
事务数据框
包含
事务id
权重
孤岛
类别

transaction   weight   island   category
1             0.3      luzon    regular
2             0.5      visayas  express
3             0.5      luzon    express
4             0.4      visayas  regular
5             1.7      visayas  regular
6             1.5      luzon    regular
第二个
费率卡数据框
包含
类别
最小重量
最大重量
费用

category    island  min weight  max weight  fee
regular     luzon     0            0.5       30
regular     luzon     0.51         3.0       40
express     luzon     0            3.0       45
regular     visayas   0            0.5       50
regular     visayas   0.51         3.0       60
express     visayas   0            3.0       65
所以我想根据包裹的重量和位置来计算费用。生成的
事务数据帧
应为

transaction      weight      island    category       fee
1                 0.3        luzon      regular        30
2                 0.5       visayas     express        65
3                 0.5        luzon      express        45
4                 0.4       visayas     regular        50
5                 1.7       visayas     regular        60
6                 1.5        luzon      regular        40
下面是
EXCEL
中关于如何计算
费用的公式

=SUMIFS(rate_card.fee, rate_card.min_weight <= transaction.weight, rate_card.max_weight >= transaction.weight, rate_card.island = transaction.island, rate_card.category = transaction.category)
=SUMIFS(rate\u card.fee,rate\u card.min\u weight=transaction.weight,rate\u card.island=transaction.island,rate\u card.category=transaction.category)
因此,我想在
Python
中使用
Pandas

希望有人能为我1个月的问题提供解决方案

注意:不是推荐的解决方案(性能问题),对于创建测试以确保使用
merge
的更好版本按预期工作可能更有用


进行以下准备:

import pandas as pd
from io import StringIO

transaction = pd.read_csv(StringIO("""
transaction   weight   island   category
1             0.3      luzon    regular
2             0.5      visayas  express
3             0.5      luzon    express
4             0.4      visayas  regular
5             1.7      visayas  regular
6             1.5      luzon    regular
"""), sep=r"\s+")

rate = pd.read_csv(StringIO("""
category    island  min_weight  max_weight  fee
regular     luzon     0            0.5       30
regular     luzon     0.51         3.0       40
express     luzon     0            3.0       45
regular     visayas   0            0.5       50
regular     visayas   0.51         3.0       60
express     visayas   0            3.0       65
"""), sep=r"\s+")
我们可以创建一个表达式来计算第一笔交易的利率总和:

rate[(rate.min_weight <= 0.3) &
     (rate.max_weight >= 0.3) &
     (rate.island=="luzon") &
     (rate.category=="regular")].fee.sum()
rate[(rate.min_weight=0.3)&
(费率岛屿=“吕宋”)&
(费率类别==“常规”)].fee.sum()
并在列表中为每一行使用该表达式,然后将其分配给一个新列,如下所示:

transaction["fee"] = [
    rate[(rate.min_weight <= t.weight) &
         (rate.max_weight >= t.weight) &
         (rate.island == t.island) &
         (rate.category == t.category)].fee.sum()
    for t in transaction.itertuples()
]
交易[“费用”]=[
速率[(速率最小重量=t重量)&
(比率.岛==t.岛)&
(费率类别==t类别)]费用总额()
对于事务中的t.itertuples()
]
这是在
类别
上,然后来自
事务
数据帧的
重量
介于
最小重量
最大重量
之间:

new = transaction.merge(rate_card, on=['category', 'island'])\
                 .query('weight.between(`min weight`, `max weight`)')\
                 .sort_values('transaction')\
                 .drop(['min weight', 'max weight'], axis=1)
new = transaction.merge(rate_card, on=['category', 'island'])\
                 .query('weight.between(`min weight`, `max weight`)')

   transaction  weight   island category  min weight  max weight  fee
0            1     0.3    luzon  regular        0.00         0.5   30
3            6     1.5    luzon  regular        0.51         3.0   40
4            2     0.5  visayas  express        0.00         3.0   65
5            3     0.5    luzon  express        0.00         3.0   45
6            4     0.4  visayas  regular        0.00         0.5   50
9            5     1.7  visayas  regular        0.51         3.0   60
或者,如果您的
pandas<0.25.0
,它还不支持
query
中的backtick列选择,请使用:

new = transaction.merge(rate_card, on=['category', 'island'])

new = new.loc[new['weight'].between(new['min weight'], new['max weight'])]\
         .sort_values('transaction')\
         .drop(['min weight', 'max weight'], axis=1)
输出

   transaction  weight   island category  fee
0            1     0.3    luzon  regular   30
4            2     0.5  visayas  express   65
5            3     0.5    luzon  express   45
6            4     0.4  visayas  regular   50
9            5     1.7  visayas  regular   60
3            6     1.5    luzon  regular   40

详细信息: 第一次合并为我们提供了:

transaction.merge(rate_card, on=['category', 'island'])

   transaction  weight   island category  min weight  max weight  fee
0            1     0.3    luzon  regular        0.00         0.5   30
1            1     0.3    luzon  regular        0.51         3.0   40
2            6     1.5    luzon  regular        0.00         0.5   30
3            6     1.5    luzon  regular        0.51         3.0   40
4            2     0.5  visayas  express        0.00         3.0   65
5            3     0.5    luzon  express        0.00         3.0   45
6            4     0.4  visayas  regular        0.00         0.5   50
7            4     0.4  visayas  regular        0.51         3.0   60
8            5     1.7  visayas  regular        0.00         0.5   50
9            5     1.7  visayas  regular        0.51         3.0   60
然后我们过滤
weight=介于最小重量和最大重量之间的所有行:

new = transaction.merge(rate_card, on=['category', 'island'])\
                 .query('weight.between(`min weight`, `max weight`)')\
                 .sort_values('transaction')\
                 .drop(['min weight', 'max weight'], axis=1)
new = transaction.merge(rate_card, on=['category', 'island'])\
                 .query('weight.between(`min weight`, `max weight`)')

   transaction  weight   island category  min weight  max weight  fee
0            1     0.3    luzon  regular        0.00         0.5   30
3            6     1.5    luzon  regular        0.51         3.0   40
4            2     0.5  visayas  express        0.00         3.0   65
5            3     0.5    luzon  express        0.00         3.0   45
6            4     0.4  visayas  regular        0.00         0.5   50
9            5     1.7  visayas  regular        0.51         3.0   60

最后两个步骤是正确排序和删除不必要的列

嗨,我已经尝试了给定的解决方案,它成功了!!谢谢!我可以知道这一行吗:
for,t in transaction.iterrows()
返回一个对的iterable
(索引,数据)
,我用它将对分配给两个变量
,t
,其中第一个只是一个下划线,用作变量名的约定,该变量名不会用于任何事情阅读上述文档后,我简化了代码以使用此答案,但在pandas数据帧上迭代是应该避免的事情之一,因为我们在
pandas
numpy
中有矢量化解决方案。很好地阅读了我的文章,谢谢你花时间回答这个问题。我确实逐行运行了您的解决方案,第一行
事务。合并(rate_card,on=['category',island'])
工作正常,但这行
出现错误。查询(
最小重量
最大重量
。是的,可能是因为您有
熊猫<0.25.0
,您可以使用
打印(pd.\uuuu版本)
进行检查。请检查我提供的第二个解决方案,其中一个应该有效,因为它不使用
.query
,并且它将比您认为正确的另一个答案快很多倍,因为这些都是矢量化方法@Lesterpajath第二种解决方案有效!非常感谢你!我将对这两种解决方案的10万个事务进行计时,看看哪一个更快。酷,你能让我知道吗?我也很好奇。@lesterpaja