You can use defaultdict
to group common suffixes, then apply a reducing function (np.subtract.reduce
) to get your output:
from collections import defaultdict
mapping = defaultdict(list)
for column in df:
if column[-1] != 4:
mapping[f"newamount{column[-1]}"].append(df[column])
else:
mapping[f"newamount{column[-1]}"].append(column)
mapping = {
key: np.subtract.reduce(value) if "4" not in key else "amount4"
for key, value in mapping.items()
}
pd.DataFrame(mapping)
newamount1 newamount2 newamount3 newamount4
0 -230 50 50 amount4
1 -370 0 300 amount4
2 -50 -50 350 amount4
3 100 -150 350 amount4
4 -200 -100 150 amount4
You could also iterate through a groupby:
mapping = {
f"newamount{key}": frame.agg(np.subtract.reduce, axis=1)
for key, frame in df.groupby(df.columns.str[-1], axis=1)
}
pd.DataFrame(mapping).assign(newamount4="amount4")
You may use the code below and adapt it if your data goes beyond 4
:
You can use pivot_longer function from pyjanitor to reshape the data before grouping and aggregating; at the moment you have to install the latest development version from github:
# install latest dev version
# pip install git+https://github.com/ericmjl/pyjanitor.git
import janitor
(
df.pivot_longer(names_to=".value",
names_pattern=".+(d)$",
ignore_index=False)
.fillna(0)
.add_prefix("newamount")
.groupby(level=0)
.agg(np.subtract.reduce)
.assign(newamount4="amount4") # edit your preferred column
)
Sticking to functions within Pandas only, we can reshape the data by stacking, before grouping and aggregating:
df.columns = df.columns.str.split("(d)", expand=True).droplevel(-1)
(
df.stack(0)
.fillna(0)
.droplevel(-1)
.groupby(level=0)
.agg(np.subtract.reduce)
.add_prefix("newamount")
.assign(newamount4="amount4")
)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…