我有一个数据帧,如果满足某个条件,我想基本上创建该行的副本。如果"日期"= Q4.22 或> AND 类型 = "实时",则应复制行此外,对于创建的每个重复项,应更新"单位"计数以反映这一点(按 id 和日期分组)建立重复项后,单位计数应反映基于相同 id 和日期的新计数。
数据
id Date set type unit energy
bb Q4.22 l live l01 20
bb Q4.22 l live l02 20
ba Q3.22 l non l01 20
aa Q4.22 l non l01 20
aa Q4.22 l live l01 20
cc Q3.22 l non l01 20
aa Q4.22 l live l02 20
期望
id Date set type unit energy
bb Q4.22 l live l01 20
bb Q4.22 l live l02 20
bb Q4.22 l live l03 20
bb Q4.22 l live l04 20
ba Q3.22 l non l01 20
aa Q4.22 l non l01 20
aa Q4.22 l live l01 20
aa Q4.22 l live l02 20
cc Q3.22 l non l01 20
aa Q4.22 l live l03 20
aa Q4.22 l live l04 20
行为
pd.concat([df, df.loc[(df['Date'] == > 'Q4.22') & (df['live'] == 'live')]])
但是,我仍然需要向创建的新副本添加计数器。 任何建议不胜感激。
尝试:
- 将日期列转换为时间戳
- 使用过滤后的数据
concat
原始数据 groupby
获取"id"和"Date"的cumcount
并相应地设置"单位">
df["Date"] = pd.to_datetime(df["Date"].str.replace(r"(Qd).(d+)", r"2-1",regex=True))
output = pd.concat([df, df[df["Date"].ge(pd.Timestamp("2022-10-01"))&df["type"].eq("live")]], ignore_index=True)
output["unit"] = output["set"]+output.groupby(["id", "Date"]).cumcount().add(1).astype(str).str.zfill(2)
output = output.sort_values("id", ignore_index=True)
#convert Date back to original format if needed
output["Date"] = output["Date"].dt.to_period("Q").astype(str).str.replace(r"dd(d+)(Qd)",r"2.1",regex=True)
>>> output
id Date set type unit energy
0 aa Q4.22 l non l01 20
1 aa Q4.22 l live l02 20
2 aa Q4.22 l live l03 20
3 aa Q4.22 l live l04 20
4 aa Q4.22 l live l05 20
5 ba Q3.22 l non l01 20
6 bb Q4.22 l live l01 20
7 bb Q4.22 l live l02 20
8 bb Q4.22 l live l03 20
9 bb Q4.22 l live l04 20
10 cc Q3.22 l non l01 20
首先,如注释中所述,我们需要将一些 df 列转换为更方便的类型:
int
unit
(去除任何字符),pd.Period
Date
.
df2 = df.assign(
unit=df['unit'].str.extract(r'(d+)').astype(int),
period=df['Date'].str.replace(r'^(Qd)D*(d+)$', r'21', regex=True).apply(pd.Period)
)
>>> df2
id Date set type unit energy period
0 bb Q4.22 l live 1 20 2022Q4
1 bb Q4.22 l live 2 20 2022Q4
2 ba Q3.22 l non 1 20 2022Q3
3 aa Q4.22 l non 1 20 2022Q4
4 aa Q4.22 l live 1 20 2022Q4
5 cc Q3.22 l non 1 20 2022Q3
6 aa Q4.22 l live 2 20 2022Q4
>>> df2.dtypes
id object
Date object
set object
type object
unit int64
energy int64
period period[Q-DEC]
dtype: object
完成此操作后,现在我们可以继续问题本身的逻辑。
ix_repeat = (df2['period'] >= pd.Period('2022-Q4')) & (df2['type'] == 'live')
r = df2.loc[ix_repeat]
r.assign(unit=r['unit'] + r.groupby(['id', 'period'])['unit'].transform(max))
>>> r
id Date set type unit energy period
0 bb Q4.22 l live 3 20 2022Q4
1 bb Q4.22 l live 4 20 2022Q4
4 aa Q4.22 l live 3 20 2022Q4
6 aa Q4.22 l live 4 20 2022Q4
# finally
df2 = pd.concat([df2, r])
可选:将单元恢复到其奇怪的字符串版本:
df2 = df2.assign(unit=df2['set'] + df2['unit'].astype(str).str.zfill(2))
>>> df2
id Date set type unit energy period
0 bb Q4.22 l live l01 20 2022Q4
1 bb Q4.22 l live l02 20 2022Q4
2 ba Q3.22 l non l01 20 2022Q3
3 aa Q4.22 l non l01 20 2022Q4
4 aa Q4.22 l live l01 20 2022Q4
5 cc Q3.22 l non l01 20 2022Q3
6 aa Q4.22 l live l02 20 2022Q4
0 bb Q4.22 l live l03 20 2022Q4
1 bb Q4.22 l live l04 20 2022Q4
4 aa Q4.22 l live l03 20 2022Q4
6 aa Q4.22 l live l04 20 2022Q4