首页 > 解决方案 > python:在数据帧范围内填充元组中的元组

问题描述

我有 4 个投资组合 a、b、c、d,它们可以在一段时间内采用“不”或“拥有”的值。(下面包含的代码以方便复制)

ano=('a','no',datetime(2018,1,1), datetime(2018,1,2))
aown=('a','own',datetime(2018,1,3), datetime(2018,1,4))
bno=('b','no',datetime(2018,1,1), datetime(2018,1,5))
bown=('b','own',datetime(2018,1,6), datetime(2018,1,7))
cown=('c','own',datetime(2018,1,9), datetime(2018,1,10))
down=('d','own',datetime(2018,1,9), datetime(2018,1,9))

sch=pd.DataFrame([ano,aown,bno,bown,cown,down],columns=['portf','base','st','end'])

日程总结:

    portf   base    st          end
0   a       no      2018-01-01  2018-01-02
1   a       own     2018-01-03  2018-01-04
2   b       no      2018-01-01  2018-01-05
3   b       own     2018-01-06  2018-01-07
4   c       own     2018-01-09  2018-01-10
5   d       own     2018-01-09  2018-01-09  

我已经尝试过:创建一个持有数据框并根据时间表填写值。不幸的是,第一个投资组合“a”被覆盖

df=pd.DataFrame(index=pd.date_range(min(sch.st),max(sch.end)),columns=['portf','base'])
for row in range(len(sch)):
        df.loc[sch['st'][row]:sch['end'][row],['portf','base']]= sch.loc[row,['portf','base']].values

            portf   base
2018-01-01  b       no
2018-01-02  b       no
2018-01-03  b       no
2018-01-04  b       no
2018-01-05  b       no
2018-01-06  b       own
2018-01-07  b       own
2018-01-08  NaN     NaN
2018-01-09  d       own
2018-01-10  c       own

所需的输出:

2018-01-01  (('a','no'), ('b','no'))
2018-01-02  (('a','no'), ('b','no'))
2018-01-03  (('a','own'), ('b','no'))
2018-01-04  (('a','own'), ('b','no'))
2018-01-05  ('b','no')
...

我确信有一种更简单的方法可以实现这一点,但可能这是我以前没有遇到过的一个例子。提前谢谢了!

标签: pythonpandasdataframe

解决方案


我会以不同的方式组织数据,索引是日期,portf 的列和值是基数。

首先,我们需要重塑数据并重新采样到每日字段。然后是一个简单的支点。

cols = ['portf', 'base']
s = (df.reset_index()
       .melt(cols+['index'], value_name='date')
       .set_index('date')
       .groupby(cols+['index'], group_keys=False)
       .resample('D').ffill()
       .drop(columns=['variable', 'index'])
       .reset_index())

res = s.pivot(index='date', columns='portf')
res = res.resample('D').first()  # Recover missing dates between

输出res

           base               
portf         a    b    c    d
2018-01-01   no   no  NaN  NaN
2018-01-02   no   no  NaN  NaN
2018-01-03  own   no  NaN  NaN
2018-01-04  own   no  NaN  NaN
2018-01-05  NaN   no  NaN  NaN
2018-01-06  NaN  own  NaN  NaN
2018-01-07  NaN  own  NaN  NaN
2018-01-08  NaN  NaN  NaN  NaN
2018-01-09  NaN  NaN  own  own
2018-01-10  NaN  NaN  own  NaN

如果您需要其他输出,我们可以通过一些不太理想的Series.apply调用到达那里。这对于大型 DataFrame 来说是非常糟糕的;我会认真考虑保留上述内容。

s.set_index('date').apply(tuple, axis=1).groupby('date').apply(tuple)

date
2018-01-01      ((a, no), (b, no))
2018-01-02      ((a, no), (b, no))
2018-01-03     ((a, own), (b, no))
2018-01-04     ((a, own), (b, no))
2018-01-05              ((b, no),)
2018-01-06             ((b, own),)
2018-01-07             ((b, own),)
2018-01-09    ((c, own), (d, own))
2018-01-10             ((c, own),)
dtype: object

推荐阅读