首页 > 解决方案 > 如果定义了数据列的限制,则按默认值填充行

问题描述

我需要根据和列=1中的信息在 DataFrame 中按默认值填充行。 因此,在行中填充分隔列的限制是基于.StartFinish
['Start', 'Finish']

数据框,df1是:

ID  Car       Jan17     Jun18  Dec18  Apr19   Start   Finish                           
0   Nissan     0.0       1.7    3.7    0.0    Jun18   Dec18   
1   Porsche    10.0      0.0    2.8    3.5    Jan17   Apr19 
2   Golf       0.0       1.7    3.0    2.0    Jun18   Apr19 
3   Toyota     1.0       0.0    3.0    5.2    Jan17   Apr19 
4   Mazda      0.0       0.0    3.0    4.2    Dec18   Apr19
5   Mercedes   0.0       0.0    0.0    7.2    Apr19   Apr19
6   Passat     0.0       3.0    0.0    0.0    Jun18   Jun18

例如,如果有一行 #0: Start = Jun18Finish = Dec18.

行#0 中的值应填充 1为列,从Jun18until 开始 到Dec18

我尝试使用numpy.sign()函数,但如果0.0在两个非零值之间,则会出现错误的结果。

预期结果是df2

ID  Car       Jan17     Jun18  Dec18  Apr19   Start   Finish                           
0   Nissan     0.0       1.0    1.0    0.0    Jun18   Dec18   
1   Porsche    1.0       1.0    1.0    1.0    Jan17   Apr19 
2   Golf       0.0       1.0    1.0    1.0    Jun18   Apr19 
3   Toyota     1.0       1.0    1.0    1.0    Jan17   Apr19 
4   Mazda      0.0       0.0    1.0    1.0    Dec18   Apr19
5   Mercedes   0.0       0.0    0.0    1.0    Apr19   Apr19
6   Passat     0.0       1.0    0.0    0.0    Jun18   Jun18

标签: pythonpandasdataframenumpy

解决方案


get_dummies+interpolate

这要求您的列按时间顺序排序,并且开始和完成在理想情况下始终存在于列名中。

df = df.set_index(['ID', 'Car', 'Start', 'Finish'])

s1 = (pd.get_dummies(df.index.get_level_values('Start'))
        .reindex(df.columns, axis=1)
        .replace(0, np.NaN))
s2 = (pd.get_dummies(df.index.get_level_values('Finish'))
        .reindex(df.columns, axis=1)
        .replace(0, np.NaN))

res = s1.combine_first(s2).interpolate(axis=1, limit_area='inside').fillna(0, downcast='infer')
res.index = df.index
res = res.reset_index()

输出res

   ID       Car  Start Finish  Jan17  Jun18  Dec18  Apr19
0   0    Nissan  Jun18  Dec18      0      1      1      0
1   1   Porsche  Jan17  Apr19      1      1      1      1
2   2      Golf  Jun18  Apr19      0      1      1      1
3   3    Toyota  Jan17  Apr19      1      1      1      1
4   4     Mazda  Dec18  Apr19      0      0      1      1
5   5  Mercedes  Apr19  Apr19      0      0      0      1
6   6    Passat  Jun18  Jun18      0      1      0      0

StartFinish已经从数据本身派生的情况下(似乎是第一个和最后一个非零列),您可以跳过所有虚拟对象并where在原始 DataFrame 上使用。

df = df.set_index(['ID', 'Car', 'Start', 'Finish'])
res = (df.where(df.ne(0))
         .clip(1,1)
         .interpolate(axis=1, limit_area='inside')
         .fillna(0, downcast='infer')
         .reset_index())

推荐阅读