如何基于Pandas Python中的条件在两个不同数据框之间进行列操作

时间:2019-11-23 20:21:49

标签: python pandas dataframe

我一直试图根据条件在两个数据帧Data1和Data 2之间执行数学运算。

1 个答案:

答案 0 :(得分:0)

请注意,对于某些帐户,您执行个以上操作, 两者传入和传出。

因此,为了在帐户余额中反映帐户之间的转移, 以符合会计规则的方式, 您应按以下方式处理数据:

  1. data1 中的索引设置为帐户编号(对于 轻松访问与特定帐户相关的行)。
  2. data1 中创建一个名为 New Balance 的新列,最初填充 数据来自 Balance
  3. 查看 data2 中的行(有关帐户之间的转帐)。
  4. 在每个循环中,从当前行读取:
    • 去往帐户,
    • 收款帐户
    • 金额。
  5. 处理当前交易,执行以下操作:
    • data1 中找到索引== 去往帐户的行,
    • 新金额字段中减去金额
    • data1 中找到索引== 传入帐户的行,
    • Amount 添加到 New Amount 字段。

执行此操作的代码是:

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 帐户,执行了以下操作:

  • 向帐户编号 9 $ 23.00 输出,
  • 从帐户 7 中输入
  • $ 35.50 ,
  • 输出 $ 423.00 到帐户 16

(币种可能不同)。

所以:

2356.00 - 23.00 + 35.50 - 423.00 = 1945.50

(不是其他解决方案中的 2333.0 )。

如何处理透支尝试

在截至23:32Z的评论中,您询问了还原转移 导致支出帐户余额为负。

我认为与其还原它们,更简便,更自然的方法是 通过检查传出帐户是否具有扩展现有循环 足够的钱( data1 > = row.Amount 的相应行中的 New Balance )。

如果不是,那么:

  • 既不从支出帐户中减去也不向其添加 应该执行收货(收货)
  • 此交易应(在 data1 中)标记为已拒绝。

在此变体中,代码应类似于:

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)(与该列中的所有其他元素相同)。