猿问

要锁定的数据帧单元格,并用于运行余额计算的条件是同一行上另一个单元格的结果

假设我有以下数据帧:


import pandas as pd

df = pd.DataFrame()


df['A'] = ('1/05/2019','2/05/2019','3/05/2019','4/05/2019','5/05/2019','6/05/2019','7/05/2019','8/05/2019','9/05/2019','10/05/2019','11/05/2019','12/05/2019','13/05/2019','14/05/2019','15/05/2019','16/05/2019','17/05/2019','18/05/2019','19/05/2019','20/05/2019')


df['B'] = ('SIT','SCLOSE', 'SHODL', 'SHODL', 'SHODL', 'SHODL', 'SHODL', 'SELL','SIT','SIT','BCLOSE', 'BHODL', 'BHODL', 'BHODL', 'BHODL', 'BHODL', 'BHODL','BUY','SIT','SIT')


df['C'] = (0.00,1.00,10.00, 5.00,6.00,-6.00, 6.00, 0.00,0.00,0.00,-8.00,33.00,-15.00,6.00,-1.00,5.00,10.00,0.00,0.00,0.00)


df.loc[19, 'D'] = 100.0000

可以看出,我从最后一行的100开始D列。


我正在尝试为列D编写计算代码,因此从底部行(第19行)开始,当B列上显示买入或卖出时,D列上的数字被锁定(例如100),并用于基于每个SHODL或BHODL的col C的计算,直到显示BCLOSE或SCLOSE之后的行。


锁定的数字用于根据列 C 中的百分比计算运行余额。如您在第 16 行中看到的,C 列的“10”表示 10%。当 100 的 10% = 10 时,新的运行平衡为 110。


第 15 行 C 列有 5%,因此将 5 添加到运行余额中以产生 115。


下一行 14 列 C 具有 -1% 的变化,因为 100 的 1% 是 = 1,因此新的运行余额是 114,依此类推。


以下是运行正确的代码后,应在数据帧的 col D 中返回的结果


df['D'] = ('158.60','158.60', '157.30', '144.30', '137.80', '130.00', '137.80', '130.00','130.00','130.00','130.00', '138.00', '105.00', '120.00', '114.00', '115.00', '110.00','100.00','100.00','100.00')

这种情况一直持续到 SCLOSE 或 BCLOSE 显示为 BCLOSE 或 SCLOSE 行是计算运行余额的最后一行。


如您所见,当显示新的买入或卖出时,此过程将重新启动。


慕妹3242003
浏览 99回答 3
3回答

喵喵时光机

下一个起始值取决于上一组的最后一个值,因此我认为它无法矢量化。它需要某种迭代过程。我想出了在groupby的组上进行迭代的解决方案。反转并分配给 。处理每组组并将最终组列表分配给原始组dfdf1df1dfdf1 = df[::-1]s = df1.B.isin(['BCLOSE','SCLOSE']).shift(fill_value=False).cumsum()grps = df1.groupby(s)init_val= 100l = []for _, grp in grps:    s = grp.C * 0.01 * init_val    s.iloc[0] = init_val    s = s.cumsum()    init_val = s.iloc[-1]    l.append(s)df['D'] = pd.concat(l)Out[50]:             A       B     C      D0    1/05/2019     SIT   0.0  158.61    2/05/2019  SCLOSE   1.0  158.62    3/05/2019   SHODL  10.0  157.33    4/05/2019   SHODL   5.0  144.34    5/05/2019   SHODL   6.0  137.85    6/05/2019   SHODL  -6.0  130.06    7/05/2019   SHODL   6.0  137.87    8/05/2019    SELL   0.0  130.08    9/05/2019     SIT   0.0  130.09   10/05/2019     SIT   0.0  130.010  11/05/2019  BCLOSE  -8.0  130.011  12/05/2019   BHODL  33.0  138.012  13/05/2019   BHODL -15.0  105.013  14/05/2019   BHODL   6.0  120.014  15/05/2019   BHODL  -1.0  114.015  16/05/2019   BHODL   5.0  115.016  17/05/2019   BHODL  10.0  110.017  18/05/2019     BUY   0.0  100.018  19/05/2019     SIT   0.0  100.019  20/05/2019     SIT   0.0  100.0        

慕斯王

下面的这篇文章应该可以帮助你。它产生预期的输出,并且速度相对较快,因为它避免了对数据帧行的直接迭代。endpoints = [df.first_valid_index(), df.last_valid_index()]# occurrences of 'BCLOSE' or 'SCLOSE'breakpoints = df.index[(df.B =='BCLOSE') | (df.B == 'SCLOSE')][::-1]# remove the endpoints of the dataframe that do not break the structurebreakpoints = breakpoints.drop(endpoints, errors='ignore')PERCENTAGE_CONST = 100top = 100  # you can specify any initial value herefor i in range(len(breakpoints) + 1):    prv = breakpoints[i - 1] - 1 if i else -1  # previous or first breakpoint    try:        nex = breakpoints[i] - 1  # next breakpoint    except IndexError:        nex = None  # last breakpoint    # cumulative sum of appended to 'D' column    res = top + (df['C'][prv: nex: -1] * top / PERCENTAGE_CONST).cumsum()[::-1]    df.loc[res.index, 'D'] = res    # saving the value that will be the basis for percentage calculations    # for the next breakpoint    top = res.iloc[0]

红糖糍粑

我认为有一种更优化和pythonic的方法可以解决这个问题。但是一个带有迭代的解决方案:df['D'] = pd.to_numeric(df['D'])df['C'] = pd.to_numeric(df['C'])D_val = Nonefor i in range(len(df)-1, 0, -1):    if df.loc[i, 'B'] == 'BUY':        D_val = df.loc[i, 'D']        continue    if D_val is None:        continue    df.loc[i, 'D'] = df.loc[i+1, 'D'] + (D_val * df.loc[i, 'C']/100)每次遇到 in 时,您都会更新 .我们还可以有一个停止的条件,如OP所提到的,如 或 。BUYcolumn DD_valSCLOSEBCLOSE
随时随地看视频慕课网APP

相关分类

Python
我要回答