根据条件

时间:2016-08-12 13:18:58

标签: python loops python-3.x for-loop

我有5周的产品和商店组合销售数据。在5周内,前三个可以进行促销活动。第一个是促销,第二个或第三个或全部三个,或者没有一个是促销。所以总共有8个条件。现在我想用循环计算python中的移动平均类事物。简单来说,我将根据支票计算平均值,如果特定周是促销,则以不同方式计算。 (每周循环的开始和结束如下

表1

                week    week    week    week    week
                1       2       3       4       5
loop_start_1    1       1       1       2       3
loop_end_1      3       4       5       5       5
loop_start_2    1       1       2       3       4
loop_end_2      2       3       4       5       5

对于第1周,我将取第1周,第2周和第3周的平均值,但对于第2周,我将取1,2,3,4的平均值,依此类推。现在如果一周是促销,这种情况会改变。输入我的数据:

表2

prod_id store_id    sales_week1 sales_week2 sales_week3 sales_week4  sales_week5    promo_1 promo_2 promo_3 promo_4 promo_5
12345     22222         40          44          50          20            21            0       0       0       0       0
12346     22222         82          85          51          72            97            1       0       0       0       0
12347     22222         74          113         31          25            19            0       1       0       0       0
12348     22222         74          105         195         216           142           0       0       1       0       0
12349     22222         78          81          23          10            67            1       1       0       0       0
12243     22222         159         190         223         137           89            0       1       1       0       0
12240     22222         591         457         556         278           726           1       0       1       0       0
22240     22222         76          49          84          132           121           1       1       1       0       0

最多可以有8种不同的组合。根据前三个星期我们有哪些促销活动。我希望如下(基于下面提到的循环的移动平均值)

表3

prod_id store_id    sales_week1 sales_week2 sales_week3 sales_week4  sales_week5    promo_1 promo_2 promo_3 promo_4 promo_5
12345     22222         44.6667         38.5            35          33.75             30.3333            0       0      0       0       0
12346     22222         82              69.3333         76.25       76.25             73.3333            1       0      0       0       0
12347     22222         52.5            113             37.25       25                25                 0       1      0       0       0
12348     22222         89.5            131.6667        195         154.3333          179                0       0      1       0       0
12349     22222         79.5            79.5            33.3333     33.3333           33.3333            1       1      0       0       0
12243     22222         159             206.5           206.5       113               113                0       1      1       0       0
12240     22222         591             367.5           556         487               502                1       0      1       0       0
22240     22222         62.5            69.6667         66.5        126.5             126.5              1       1      1       0       0

现在我有一个虚拟代码(8个条件),我想根据促销条件转换为循环。如果条件不要写这么多。请提前帮助谢谢。

if promo_1 =1 then:
sales_new[1]=sales_old[1]
sales_new[2]=average(sales_old[2],sales_old[3],sales_old[4])
sales_new[3]=avergae(sales_old[2],sales_old[3],sales_old[4],sales[5])
sales_new[4]=avergae(sales_old[2],sales_old[3],sales_old[4],sales[5])
sales_new[5]=avergae(sales_old[3],sales_old[4],sales[5])

if promo_2 =1 then:
sales_new[1]=average(sales_old[1],sales_old[3])
sales_new[2]=sales_old[2]
sales_new[3]=avergae(sales_old[1],sales_old[3],sales_old[4],sales[5])
sales_new[4]=avergae(sales_old[3],sales_old[4],sales[5])
sales_new[5]=avergae(sales_old[3],sales_old[4],sales[5])

if promo_3 =1 then:
sales_new[1]=average(sales_old[1],sales_old[2])
sales_new[2]=average(sales_old[1],sales[2],sales[4]
sales_new[3]=sales_old[3]
sales_new[4]=avergae(sales_old[2],sales_old[4],sales[5])
sales_new[5]=avergae(sales_old[4],sales[5])

if promo_1 =1 and promo_2=1 then:
sales_new[1]=average(sales_old[1],sales_old[2])
sales_new[2]=average(sales_old[1],sales_old[2])
sales_new[3]=average(sales_old[3],sales_old[4],sales_old[5])
sales_new[4]=average(sales_old[3],sales_old[4],sales_old[5])
sales_new[5]=average(sales_old[3],sales_old[4],sales_old[5])

if promo_2 =1 and promo_3=1 then:
sales_new[1]=sales_old[1]
sales_new[2]=average(sales_old[2],sales_old[3])
sales_new[3]=average(sales_old[2],sales_old[3])
sales_new[4]=average(sales_old[4],sales_old[5])
sales_new[4]=average(sales_old[4],sales_old[5])

if promo_1 =1 and promo_3=1 then:
sales_new[1]=sales_old[1]
sales_new[2]=average(sales_old[2],sales_old[4])
sales_new[3]=sales_old[3]
sales_new[4]=average(sales_old[2],sales_old[4],sales_old[5])
sales_new[4]=average(sales_old[4],sales_old[5])

if promo_1 =1 and promo_2=1 and promo_3=1 then:
sales_new[1]=average(sales_old[1],sales_old[2])
sales_new[2]=average(sales_old[1],sales_old[2],sales_old[3])
sales_new[3]=average(sales_old[2],sales[3])
sales_new[4]=average(sales_old[4],sales_old[5])
sales_new[5]=average(sales_old[4],sales_old[5])

if promo_1 =0 and promo_2=0 and promo_3=0 then:
sales_new[1]=average(sales_old[1],sales_old[2],sales_old[3])
sales_new[2]=average(sales_old[1],sales_old[2],sales_old[3],sales_old[4])
sales_new[3]=average(sales_old[1],sales_old[2],sales_old[3],sales_old[4],sales_old[5])
sales_new[3]=average(,sales_old[2],sales_old[3],sales_old[4],sales_old[5])
sales_new[5]=average(sales_old[3],sales_old[4],sales_old[5])

商家规则

在本节中,我提供了业务规则,以阐明我的代码的要求。

在最高级别,我的目标是计算销售的移动平均值。我通过一个脚本计算新的销售数据(包含这些平均值)来自" old" (原始)数据。

对于未提升的任何一周,我们会考虑 loop_start_1和loop_end_1 ,但如果一周提升,我们会考虑 loop_start_2和loop_end_2

一个规定是每个新的周销售数据 - 默认 - 从旧周销售数据的子集中派生。这在表1中指定。例如,第1周的新销售数据(默认情况下)是根据未提升周数的第1-3周的旧销售数据计算得出的。

然而,每周可能会或可能不会是"促销"这一周,这将影响该周的旧销售数据是否可用于计算新的销售数据。 这会覆盖表1 loop_start_1和loop_end_1 指定的内容。对于促销活动,我们会考虑表1中的 loop_start_2和loop_end_2 ,特别是:

  • 如果本周没有一个促销,我们会考虑loop_start_1和loop_end_1 else
  • 如果提前三周的任何一周被提升,那么我们将考虑loop_start_2和loop_end_2

例如,如果第1周正在推广,那么我们需要执行以下操作:

  • 计算week_1_new = avg(week_1_old)

    • 表1指明我们使用旧周1-2。(loop_start_2和loop_end_2)
    • 第1周是促销,第2周不是 - 所以只需要第1周
  • 计算week_2_new = avg(week_2_old, week_3_old, week_4_old)

    • 表1指定我们使用旧周1-4。(loop_start_1和loop_end_1)
    • 第1周是促销,第2周,第3周和第2周。 4不是 - 所以大部分时间都没有促销。因此促销销售将被夸大,因此我们将其排除在平均值
    • 之外
    • 我们只考虑那些不在促销活动周的数据 - 2,3和& 4。
  • ...

另一方面,如果第1周和第2周都在推广,那么请考虑我们如何计算第1周的新销售数据:

  • week_1_new = avg(week_1_old, week_2_old)
    • 表1指定我们使用旧的周1-2。(loop_start_2和loop_end_2)
    • 第1周和第1周2正在推广 - 所以的大部分时间都是促销。我们平均花了几个星期
    • 我们只考虑促销活动的那些周的数据 - 1& 2。

另一方面,如果所有第1周和第3周都在推广,那么请考虑我们如何计算第1周的新销售数据:

  • week_1_new = avg(week_1_old) (loop_start_2和loop_end_2)仅在第一周的1-2周内进行推广。我们从不在产品升级时添加销售额,而不提升产品的那一周。因为这会夸大平均值。
  • week_2_new = avg(week_2_old,week_4_old) ((1-4中的loop_start_1和loop_end_1仅提升2和4)
  • week_3_new = avg(week_3_old)

    • 我们只考虑促销活动的那些周的数据 - 1& 3

另一方面,如果所有第1周到第3周都在推广,那么请考虑我们如何计算第1周的新销售数据:

    我们需要
  • week_1_new = avg(week_1_old,week_2_old) loop_start_2和loop_end_2
  • week_2_new = avg(week_1_old,week_2_old,week_4_old) as( loop_start_2和loop_end_2 )表示第1-3周将被考虑用于第2周的推广weeeks
  • week_3_new = avg(week_2_old,week_3_old) as( loop_start_2和loop_end_2 )表示第2-4周。但在2,3,4中只有2和3被提升。所以只需要提升周数

2 个答案:

答案 0 :(得分:1)

在撰写本文时,我对您的问题的编辑仍处于待审状态,您尚未确认我是否正确理解了您的业务规则。假设我有,这是我试图为你准备的解决方案:

from typing import Generator, Dict, List, Tuple

import numpy

TOTAL_WEEKS = 5


def create_default_sales_data_map() -> Dict[int, List[int]]:
    """
    Create and return the default mapping of old week sales data
    to new averaged week sales data.

    The mapping is a tuple specifying the (inclusive) lower and upper
    range of weeks to consider the sales data of by default when calculating
    the new sales data for the week specified by the dictionary key.

    This is based on Table 1.

    :return: the default sales data mapping
    """
    sales_data_map = {1: (1, 3), 2: (1, 4), 3: (1, 5), 4: (2, 5), 5: (3, 5)}

    return sales_data_map


def are_majority_weeks_promoted(promoted_weeks: [bool]) -> bool:
    """
    Return if the majority of weeks are promoted or not.

    :param promoted_weeks: The promotion status of each week
    :return: `true` if the majority of weeks are promoted
    """
    return sum(promoted_weeks) >= len(promoted_weeks) / 2


def calculate_new_sales_data(old_sales_data: List[int], promoted_weeks: List[bool]) -> int:
    """
    Calculate new (averaged) sales data for a week based on old (raw) sales data and the
    promotion status of the relevant weeks.

    :param old_sales_data: the old week sales data used by default (i.e. according to Table 1)
    :param promoted_weeks: the promotion status of the weeks corresponding to `old_sales_data`
    :return: the new sales data for a particular week
    """
    majority = are_majority_weeks_promoted(promoted_weeks)
    relevant_data = [data for i, data in enumerate(old_sales_data) if promoted_weeks[i] == majority]
    new_sales_data = numpy.mean(relevant_data)
    return new_sales_data


def calculate_all_new_sales_data(complete_old_sales_data: List[int], complete_promoted_weeks: List[bool]) -> Generator[int, None, None]:
    """
    Generates new sales data for all possible weeks based on the supplied sales week data.

    :param complete_old_sales_data: the complete set of information on old week sales data
    :param complete_promoted_weeks: the promotion status for all weeks
    :return: a generator for new sales data
    """
    sales_data_map = create_default_sales_data_map()
    for week, (lower, upper) in sales_data_map.items():
        old_sales_data = complete_old_sales_data[lower-1 : upper]
        promoted_weeks = complete_promoted_weeks[lower-1 : upper]
        yield calculate_new_sales_data(old_sales_data, promoted_weeks)


def query_user(total_weeks: int) -> Generator[Tuple[int, bool], None, None]:
    """
    Query the user for the old sales data values and promoted weeks and return the results.

    Each generated tuple contains the old sales data for the week, and whether the week is promoted.

    :param total_weeks: the number of weeks' worth of data to query the user for.
    :return: a generator of sales data tuples
    """
    for i in range(total_weeks):
        while True:
            try:
                old_sales_data = int(input("Total sales data for week {}: $".format(i+1)))
                break
            except ValueError:
                continue

        while True:
            promotion_status_str = input("Is week promoted (Y/N)? ").lower()
            if promotion_status_str in ["y", "n"]:
                promotion_status = promotion_status_str == "y"
                break

        yield old_sales_data, promotion_status


def main():
    old_sales_data, promoted_weeks = zip(*query_user(TOTAL_WEEKS))

    print()
    for week, new_sales_data in enumerate(calculate_all_new_sales_data(old_sales_data, promoted_weeks), 1):
        print("Week {} averaged sales data: ${:.2f}".format(week, new_sales_data))


if __name__ == '__main__':
    main()

<强>输入

Total sales data for week 1: $10
Is week promoted (Y/N)? y
Total sales data for week 2: $20
Is week promoted (Y/N)? y
Total sales data for week 3: $30
Is week promoted (Y/N)? n
Total sales data for week 4: $40
Is week promoted (Y/N)? y
Total sales data for week 5: $50
Is week promoted (Y/N)? n

<强>输出

Week 1 averaged sales data: $15.00
Week 2 averaged sales data: $23.33
Week 3 averaged sales data: $23.33
Week 4 averaged sales data: $30.00
Week 5 averaged sales data: $40.00

<强>解释

  • 对于“新”第1周,表1表示考虑“旧”第1-3周。第1周和第1周2是升级但第3周没有,所以我们只对“老”周1和1进行平均2 - 即我们平均10美元和20美元获得15美元。
  • 对于“新”第2周,默认情况下我们认为“旧”第1-4周。这些周的大部分时间(1,2和4)都得到了提升,因此我们只考虑这些和平均值。 10美元,20美元和40美元的平均价格为23.33美元。
  • ...

我们可以使用这些值来测试行为是否正确。例如,让我们这样做,以便默认为“新”销售第1周数据考虑的大部分时间不会被提升:

Total sales data for week 1: $10
Is week promoted (Y/N)? y
Total sales data for week 2: $20
Is week promoted (Y/N)? n
Total sales data for week 3: $30
Is week promoted (Y/N)? n
...
Week 1 averaged sales data: $25.00

在这种情况下,只考虑第2周和第3周。

如果提前三周都升级了怎么样?

Total sales data for week 1: $10
Is week promoted (Y/N)? y
Total sales data for week 2: $20
Is week promoted (Y/N)? y
Total sales data for week 3: $30
Is week promoted (Y/N)? y
...
Week 1 averaged sales data: $20.00

在这里,我们考虑所有周,并平均他们的销售数据。

答案 1 :(得分:0)

这会有意义吗?

sales_new[1] = average(sales_old[1],sales_old[2])
sales_new[2] = average(sales_old[1],sales_old[2],sales_old[3])
sales_new[3] = average(sales_old[2],sales_old[3],sales_old[4])
sales_new[4] = average(sales_old[3],sales_old[4],sales_old[5])
sales_new[5] = average(sales_old[4],sales_old[5])

if promo_1 then:
    sales_new[1] = sales_old[1]

if promo_2 then:
    sales_new[2] = sales_old[2]

if promo_3 then:
    sales_new[3] = sales_old[3]

if promo_4 then:
    sales_new[3] = sales_old[3]

if promo_5 then:
    sales_new[3] = sales_old[3]

计算&#39;运行&#39;平均,然后根据促销修改它。

注意:您的数组可能是基于索引的,因此它将从sales_new [0]开始。