根据在 pandas 的另一列中按顺序满足条件的出现次数创建列

问题描述 投票:0回答:2

我有一个类似于以下的数据集:

import pandas as pd

date0 = ["2020-01-31"] * 3
date1 = ["2020-02-28"] * 3
date2 = ["2020-03-31"] * 3

date = date0 + date1 + date2
acc = ["A", "B", "C"] * 3
val = [1, 0, 0, 1, 1, 0, 1, 1, 1]

df = pd.DataFrame({"date": date, "account": acc, "value": val})

目标是创建一个名为“output”的新列,它根据给定的时间序列计算基于“account”的二进制列“value”的出现次数。如果“val”列连续显示三个(或 N 个)1,则输出列为 1,否则为 0。

对于上面的数据集,这将产生:

output = [0, 0, 0, 0, 0, 0, 1, 0, 0]
df["output"] = output

此外,如果时间序列中的第 4 次迭代是 0,则序列重新开始。自然地,如果第 4 次迭代是 1,那么输出就是 1。

下面的数据集显示账户“A”在前 3 个月后就满足了标准,然后账户恢复,再次开始循环。账户“B”满足第 2-4 个月等的标准。这是大型模拟的一部分,因此矢量化解决方案是理想的。

date3 = ["2020-04-30"] * 3
val = [0, 1, 1]
acc = ["A", "B", "C"]
output = [0, 1, 0]

df2 = pd.DataFrame({"date": date3, "account": acc, "value": val, "output": output})

df3 = pd.concat([df,  df2])
python pandas numpy optimization
2个回答
0
投票

假设每个帐户每个月有一个值并且没有遗漏日期,您可以使用

groupby_rolling

df['output'] = (df.groupby('account').rolling(3)['value']
                  .sum().eq(3).astype(int).droplevel(0))
print(df)

# Output
         date account  value  output
0  2020-01-31       A      1       0
1  2020-01-31       B      0       0
2  2020-01-31       C      0       0
3  2020-02-28       A      1       0
4  2020-02-28       B      1       0
5  2020-02-28       C      0       0
6  2020-03-31       A      1       1
7  2020-03-31       B      1       0
8  2020-03-31       C      1       0

第二个例子:

df3 = pd.concat([df,  df2], ignore_index=True)  # <- ignore_index=True
df3['output2'] = (df3.groupby('account').rolling(3)['value']
                     .sum().eq(3).astype(int).droplevel(0))
print(df3)

# Output
          date account  value  output  output2
0   2020-01-31       A      1       0        0
1   2020-01-31       B      0       0        0
2   2020-01-31       C      0       0        0
3   2020-02-28       A      1       0        0
4   2020-02-28       B      1       0        0
5   2020-02-28       C      0       0        0
6   2020-03-31       A      1       1        1
7   2020-03-31       B      1       0        0
8   2020-03-31       C      1       0        0
9   2020-04-30       A      0       0        0
10  2020-04-30       B      1       1        1
11  2020-04-30       C      1       0        0

0
投票
import pandas as pd

date0 = ["2020-01-31"] * 3
date1 = ["2020-02-28"] * 3
date2 = ["2020-03-31"] * 3

date = date0 + date1 + date2
acc = ["A", "B", "C"] * 3
val = [1, 0, 0, 1, 1, 0, 1, 1, 1]

df = pd.DataFrame({"date": date, "account": acc, "value": val})

df["output"] = (~(df.groupby('account')
                    .cumsum(numeric_only=True)
                    .agg({'value': lambda n: 0 if n>3 else n})
                    .subtract(3)
                    .astype(bool)
                )).astype(int)

print(df)

结果

         date account  value  output
0  2020-01-31       A      1       0
1  2020-01-31       B      0       0
2  2020-01-31       C      0       0
3  2020-02-28       A      1       0
4  2020-02-28       B      1       0
5  2020-02-28       C      0       0
6  2020-03-31       A      1       1
7  2020-03-31       B      1       0
8  2020-03-31       C      1       0
© www.soinside.com 2019 - 2024. All rights reserved.