(数据帧的)索引序列子集不改变值

2024-09-30 02:18:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我有下表:

df = pd.DataFrame(({'code':['A121','A121','A121','H812','H812','H812','Z198','Z198','Z198','S222','S222','S222'],
                        'mode':['stk','sup','cons','stk','sup','cons','stk','sup','cons','stk','sup','cons'],
                        datetime.date(year=2021,month=5,day=1):[4,2,np.nan,2,2,np.nan,6,np.nan,np.nan,np.nan,2,np.nan],
                        datetime.date(year=2021,month=5,day=2):[1,np.nan,np.nan,3,np.nan,np.nan,2,np.nan,np.nan,np.nan,np.nan,np.nan],
                        datetime.date(year=2021,month=5,day=3):[12,5,np.nan,13,5,np.nan,12,np.nan,np.nan,np.nan,5,np.nan],
                        datetime.date(year=2021,month=5,day=4):[np.nan,1,np.nan,np.nan,4,np.nan,np.nan,np.nan,np.nan,np.nan,7,np.nan]}))
df = df.set_index('mode')


我希望实现以下目标,我希望根据一些算术计算设置cons所在的行:

cons对应的日期和代码需要设置为以下计算prev_date stk - current_date stk + sup

我尝试了以下代码:

dates = list(df.columns)
dates.remove('code')
for date in dates:
    prev_date = date - datetime.timedelta(days=1)
    if(df.loc["stk"].get(prev_date,None) is not None):
        opn_stk = df.loc["stk",prev_date].reset_index(drop=True)
        cls_stk = df.loc["stk",date].reset_index(drop=True)
        sup = df.loc["sup",date].fillna(0).reset_index(drop=True)
        cons = opn_stk - cls_stk + sup
        df.loc["cons",date] = cons

我没有收到任何错误,但是cons值根本没有改变

我怀疑这可能是因为df.loc["cons",date]是一个索引序列,而计算opn_stk - cls_stk + sup是一个未索引序列。 你知道怎么解决这个问题吗

另外,我正在使用循环来计算这个,有没有其他更有效的向量化方法


预期产量


Tags: dfdatetimedateindexnpnanyearloc
2条回答

让我们试试groupby应用程序:

def calc_cons(g):
    # Transpose
    t = g[g.columns[g.columns != 'code']].T
    # Update Cons
    g.loc[g.index == 'cons', g.columns != 'code'] = (-t['stk'].diff() +
                                                     t['sup'].fillna(0)).to_numpy()
    return g


df = df.groupby('code', as_index=False, sort=False).apply(calc_cons)
# print(df[df.index == 'cons'])
print(df)
      code  2021-05-01  2021-05-02  2021-05-03  2021-05-04
mode                                                      
stk   A121         4.0         1.0        12.0         NaN
sup   A121         2.0         NaN         5.0         1.0
cons  A121         NaN         3.0        -6.0         NaN
stk   H812         2.0         3.0        13.0         NaN
sup   H812         2.0         NaN         5.0         4.0
cons  H812         NaN        -1.0        -5.0         NaN
stk   Z198         6.0         2.0        12.0         NaN
sup   Z198         NaN         NaN         NaN         NaN
cons  Z198         NaN         4.0       -10.0         NaN
stk   S222         NaN         NaN         NaN         NaN
sup   S222         2.0         NaN         5.0         7.0
cons  S222         NaN         NaN         NaN         NaN

*假设列按日期按1天的间隔排序

尽管@Henry Ecker的回答非常优雅,但与我所做的相比,它的速度非常慢(慢了10倍多),因此我希望继续修复我的实现

我的实现按照Henry Ecker的建议进行了修复df.loc["cons",date] = cons.to_numpy()

dates = list(df.columns)
dates.remove('code')
for date in dates:
    prev_date = date - datetime.timedelta(days=1)
    if(df.loc["stk"].get(prev_date,None) is not None):
        opn_stk = df.loc["stk",prev_date].reset_index(drop=True)    # gets the stock of prev date
        cls_stk = df.loc["stk",date].reset_index(drop=True)         # gets the stock of current date
        sup = df.loc["sup",date].fillna(0).reset_index(drop=True)   # gets suplly of current date
        cons = opn_stk - cls_stk + sup
        df.loc["cons",date] = cons.to_numpy()

作为旁注: 我的实现运行在0:00:00.053309 seconds中的完整数据上(不是这个,我创建这个作为玩具示例),Henry Ecker的实现运行在0:00:00.568888 seconds中,因此速度要慢10倍以上

这可能是因为他在迭代代码,而我在迭代日期。在任何给定的时间点,我最多会有30个日期,但可能会有超过500个代码

相关问题 更多 >

    热门问题