我需要=1
根据Start
和Finish
列中的信息在DataFrame中填充默认值的行。
因此,基于定义行中填充分离列的限制['Start', 'Finish']
。
DataFrame 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 = Jun18
和 行
Finish = Dec18
。
第#0行中的值应由填充 1
,Jun18
直到〜为止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
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
在Start
和Finish
已经从数据本身派生的情况下(似乎是第一列和最后一个非零列),您可以跳过所有虚拟变量,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())
现在,这是一个很不错的解决方案。+1我不会使用插值法,而是pd.date_range。很好的解决方案。我认为这比我最初的想法更好。
是的,我认为“更安全”的选择是将所有内容转换为
datetime
可以正确处理缺失日期的方式。但这似乎是从数据开始的,Start
并且Finish
可能是从数据开始的,在这种情况下,尽管插值速度很慢,但它仍然可以工作。@ALollz,是的,您是对的,我需要在开始日期和结束日期之间填写内容,并将所有非零值都保留为
1
。现在,我遇到的问题是,当Start
和Finish
相同时,代码会将Start
直到直到的插值返回到现有的最后一列,但是应该仅将一个值替换为1并停止。例如,我在问题中添加了第6行。在这种情况下3.0
,仅应将Jun18
列替换为1,而不要继续Apr19
列。谢谢@辛迪好抓住。请查看更新。我们需要将
limit_area='inside'
参数添加到插值@ALollz,是的,更新后可以正常工作。非常感谢!