我有一个一百万行的 Dataframe
Dataframe 包括ID、FDAT、LACT列
每个ID可能有多个FDAT和LACT。该ID的每个LACT的FDAT应该相同。有时候会有一个缺失的FDAT,我想用该ID中与该LACT匹配的FDAT来填充
示例数据
ID FDAT LACT
1 1/1/2020 1
1 1/1/2020 1
1 1/1/2021 2
1 NA 2
1 1/1/2021 2
1 1/1/2022 3
在本例中,NA应为1/1/2021
我使用下面的代码来完成这个任务。不幸的是它非常慢。我只想填充缺失的值。我不想改变任何非空的FDAT条目。
df.sort_values(["ID",'DATE'], inplace=True)
df.loc[:, 'FDAT'] = df.groupby(['ID','LACT']).fillna(method="ffill")
df.loc[:, 'FDAT'] = df.groupby(['ID','LACT']).fillna(method="bfill")
我在寻找能做同样事情但运行速度更快的代码。
2条答案
按热度按时间agxfikkp1#
下面是一些矢量化代码,它可以在一秒钟内处理100万行。
应用于示例输入数据:
解释
基本思想是对
(ID, LACT): FDAT
进行一个干净的Map,为了高效地实现这一点,我们使用df
的一个版本,其中索引由[ID, LACT]
组成:我们删除
NaN
值和重复的索引:现在,我们可以将
a
中的所有NaN
替换为来自c
的值,其中c
对应于相同的索引['ID', 'LACT']
:此时,我们只想获取这些值,它们的顺序与原始
df
中的顺序相同,并且在用这些值替换df['FDAT']
时忽略索引(因此是.to_numpy()
部分)。为了使原始df
保持不变(我强烈反对任何更改输入的代码,除非明确声明),我们使用习惯用法df.assign(FDAT=...)
派生一个新的df
,并返回它。给出了上面的函数。其他观察结果
注意,其他列(如果有的话)会被保留,为了说明这一点并度量性能,让我们编写一个随机数
df
的生成器:小例子:
速度
一百万行不到一秒。
jdg4fx2g2#
如下图所示,我给出了一个更快的替代方案,以及原始时间和计算时间:
返回:
而您的解决方案:
退货:
因此,同时使用
transform
和fffill
大约要快1.5倍。注意,在您的代码示例中,sort_values()
不包括在时间中。因此,我估计使用我建议的方法应该要快2.5倍。