我一直试图根据条件在两个数据帧Data1和Data 2之间执行数学运算。
答案 0 :(得分:0)
请注意,对于某些帐户,您执行个以上操作, 两者传入和传出。
因此,为了在帐户余额中反映帐户之间的转移, 以符合会计规则的方式, 您应按以下方式处理数据:
执行此操作的代码是:
data1.set_index('Account Number', inplace=True)
data1['New Balance'] = data1.Balance
for _, row in data2.iterrows():
outAcnt = int(row['Outgoing Account'])
inAcnt = int(row['Ingoing Account'])
amt = row.Amount
data1.at[outAcnt, 'New Balance'] -= amt
data1.at[inAcnt, 'New Balance'] += amt
在循环后 print(data1)时,对于您的数据,您将得到:
Balance New Balance
Account Number
1 2356.0 1945.5
3 452.5 -2874.5
5 120.0 2197.0
7 124.0 13.5
9 4582.0 4595.0
12 230.0 497.5
14 9.5 -2001.5
16 423.0 -381.0
18 235.0 -66.5
20 12.0 4619.0
通过这种方式,新余额反映了该工作日内执行的转帐, 例如对于 1 帐户,执行了以下操作:
(币种可能不同)。
所以:
2356.00 - 23.00 + 35.50 - 423.00 = 1945.50
(不是其他解决方案中的 2333.0 )。
在截至23:32Z的评论中,您询问了还原转移 导致支出帐户余额为负。
我认为与其还原它们,更简便,更自然的方法是 通过检查传出帐户是否具有扩展现有循环 足够的钱( data1 > = row.Amount 的相应行中的 New Balance )。
如果不是,那么:
在此变体中,代码应类似于:
data1.set_index('Account Number', inplace=True)
data1['New Balance'] = data1.Balance
data2 = data2.assign(Refused=False)
for transKey, row in data2.iterrows():
outAcnt = int(row['Outgoing Account'])
inAcnt = int(row['Ingoing Account'])
amt = row.Amount
balBefore = data1.at[outAcnt, 'New Balance']
if balBefore >= amt: # The charged amount has enough money
data1.at[outAcnt, 'New Balance'] -= amt
data1.at[inAcnt, 'New Balance'] += amt
result = 'OK'
else:
data2.at[transKey, 'Refused'] = True
result = 'Refused'
print(f'{outAcnt:3} {inAcnt:3} {amt:8.2f} {balBefore:8.2f} {result}')
出于演示目的,我添加了有关两个帐户的打印输出 号码,转账金额, 交易和“确定/拒绝”状态。
这次,“跟踪”打印输出为:
1 9 23.00 2356.00 OK
18 12 242.50 235.00 Refused
7 14 120.00 124.00 OK
16 3 1227.00 423.00 Refused
20 7 45.00 12.00 Refused
5 18 59.00 120.00 OK
3 14 5.00 452.50 OK
3 20 4534.00 447.50 Refused
3 9 15.00 447.50 OK
7 1 35.50 4.00 Refused
9 16 25.00 4620.00 OK
16 12 25.00 448.00 OK
18 20 118.00 294.00 OK
14 5 2136.00 134.50 Refused
1 16 423.00 2333.00 OK
, data1 中的最终结果如下:
Balance New Balance
Account Number
1 2356.0 1910.0
3 452.5 432.5
5 120.0 61.0
7 124.0 4.0
9 4582.0 4595.0
12 230.0 255.0
14 9.5 134.5
16 423.0 846.0
18 235.0 176.0
20 12.0 130.0
还使用添加的列打印 data2 ,标记拒绝状态。
请注意, data2 中的时间列仅包含数字,并且默认情况下 读取为 int64 类型。如果要将 Time 列转换为 time 类型, 运行:
data2['Time'] = pd.to_datetime(data2['Time'], format='%H%M').dt.time
更准确地说,此列的 pandasonic 类型为 object
(实际上是定义的数字数据类型以外的其他东西),但是如果您
尝试读取个体值,例如data2.iat[0,0]
,您将获得
datetime.time(9, 15)
(与该列中的所有其他元素相同)。