【问题标题】:Python - Lock values in iteration processPython - 在迭代过程中锁定值
【发布时间】:2021-02-22 13:10:20
【问题描述】:

我声明这不是 pytho 专家。通过这篇文章,我想了解如何使用上述流程中的锁定值迭代流程(例如:for 循环)。

我将逐步解释我在寻找什么。 一开始我建立了一个数据框。

import pandas as pd

# Build the Dataframe

data = {'Col_1' : pd.Series(list(range(10,53,3))),
   'Col_2' : pd.Series(list(range(30,45))),
   'Col_3' : pd.Series([0,0,1,0,0,-1,0,0,1,0,0,0,-1,0,0])}

data = pd.DataFrame(data)
data['Result'] = 0
data['Result_1'] = 0

# Define a constant

c = 2

下面是上面代码的结果。

    Col_1  Col_2  Col_3  Result  Result_1
0      10     30      0       0         0
1      13     31      0       0         0
2      16     32      1       0         0
3      19     33      0       0         0
4      22     34      0       0         0
5      25     35     -1       0         0
6      28     36      0       0         0
7      31     37      0       0         0
8      34     38      1       0         0
9      37     39      0       0         0
10     40     40      0       0         0
11     43     41      0       0         0
12     46     42     -1       0         0
13     49     43      0       0         0
14     52     44      0       0         0

话虽如此,我想创建一个迭代过程(例如:for循环),它追求以下条件:

  1. 如果 Col_3 = 1 锁定 Col_1 中的值,则使用这个 last 来执行 Col_2 中的操作,直到 Col_3 中的值等于 -1,并将结果放入 'Result' 列。

  2. 如果 Col_3 = -1 使用前一点的锁定值,则对“前一点”执行相同的操作,并将获得的结果乘以定义的常量“c”。将结果放入“Result_1”列。

  3. 否则将 0 值放入两列('Result' 和 'Result_1')。

下面显示了迭代过程是如何工作的。

    Col_1  Col_2  Col_3   Result   Result_1
0      10     30      0        0          0
1      13     31      0        0          0
2      16     32      1  (16-32)          0
3      19     33      0  (16-33)          0
4      22     34      0  (16-34)          0
5      25     35     -1        0  (16-35)*c
6      28     36      0        0          0
7      31     37      0        0          0
8      34     38      1  (34-38)          0
9      37     39      0  (34-39)          0
10     40     40      0  (34-40)          0
11     43     41      0  (34-41)          0
12     46     42     -1        0  (34-42)*c
13     49     43      0        0          0
14     52     44      0        0          0

下面显示了预期的数据框。

    Col_1  Col_2  Col_3  Result  Result_1
0      10     30      0       0         0
1      13     31      0       0         0
2      16     32      1     -16         0
3      19     33      0     -17         0
4      22     34      0     -18         0
5      25     35     -1       0       -38
6      28     36      0       0         0
7      31     37      0       0         0
8      34     38      1      -4         0
9      37     39      0      -5         0
10     40     40      0      -6         0
11     43     41      0      -7         0
12     46     42     -1       0       -16
13     49     43      0       0         0
14     52     44      0       0         0

总之,我知道我可以以更简单的方式获得相同的结果,而无需使用迭代器,但在这种特定情况下,我正在寻找可以向我解释如何完成迄今为止通过使用迭代器(迭代器可以是 for 循环、while 或其他)。

提前感谢您的任何帮助!

【问题讨论】:

    标签: python loops dynamic iterator block


    【解决方案1】:

    一种方法是使用for-loop 遍历data 的索引:

    on = False  # Switch starts with off (= False)
    for i in data.index:
        if on:
            if data.at[i, 'Col_3'] == -1:  # Check if -1 in Col_3 is reached
                on = False  # Switch off (= False)
                data.at[i, 'Result_1'] = c * (col_1 - data.at[i, 'Col_2'])
            else:
                data.at[i, 'Result'] = col_1 - data.at[i, 'Col_2']
        else:
            if data.at[i, 'Col_3'] == 1:  # Check if 1 in Col_3 is reached
                on = True  # Switch on (= True)
                col_1 = data.at[i, 'Col_1']  # Store value of Col_1 in this position
                data.at[i, 'Result'] = col_1 - data.at[i, 'Col_2']
    

    变量on 跟踪程序是否处于哪个“阶段”(在 Col_3 中是否介于 1 和 -1 之间)。

    带有while 的版本会遍历索引:

    iterator = iter(data.index)
    while True:
        try:
            i = next(iterator)
        except StopIteration:
            break
        if data.at[i, 'Col_3'] == 1:  # Check for 1 in Col_3
            col_1 = data.at[i, 'Col_1']  # Store value of Col_1 in this position
            while data.at[i, 'Col_3'] != -1:
                data.at[i, 'Result'] = col_1 - data.at[i, 'Col_2']
                try:
                    i = next(iterator)
                except StopIteration:
                    break
            # Value -1 in Col_3 reached
            data.at[i, 'Result_1'] = c * (col_1 - data.at[i, 'Col_2'])
    

    如果没有for,则需要使用next() 显式完成迭代。这是在try-except 块内完成的,以捕获StopIteration 异常,然后将break 排除在循环之外。如果您想在不捕获的情况下查看会发生什么,请尝试:

    iterator = iter(data.index)
    while True:
        next(iterator)
    

    在这两个版本中,我都省略了第 3 步,因为零已经在那里了。

    一般来说:for 循环是一个更“受控”的环境。 while 循环通常提供更大的灵活性,但需要显式迭代。

    (还有其他迭代 DataFrame 的方法,例如 data.iterrows()data.itertuples()。)

    【讨论】:

    • 天才,这正是我想要的。非常感谢 Timus,非常感谢您花时间回答我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-21
    • 2021-03-08
    • 2017-10-23
    • 1970-01-01
    • 2019-01-10
    • 1970-01-01
    相关资源
    最近更新 更多