如果行具有相同的“A 列”值,则用最后一个已知值填充空的“B 列”单元格

Posted

技术标签:

【中文标题】如果行具有相同的“A 列”值,则用最后一个已知值填充空的“B 列”单元格【英文标题】:Filling empty "B column" cells with last known value if rows have same "A column" value 【发布时间】:2020-02-13 14:30:05 【问题描述】:

我对 Python 和数据科学真的很陌生。

我有一个大数据集(有 100K+ 行),在这个数据集中我有两列 ABA 是日期时间列,B 是字符串。

B 列有一些 NaN 值,我想用最新的已知 B 列值填充这些 NaN 值,条件是我的空 B 列行和已填充的 B 列行在同一天、同一个月和同一年(列A)。

让我解释一下我的自我:

假设这是我的输入:

df=pd.DataFrame('A': ["2019-03-13 08:12:23", "2019-03-13 07:10:18", "2019-03-20 08:12:23", "2019-03-13 08:12:23", "2019-03-15 10:35:53", "2019-03-20 11:12:23"], 'B': ["B1", "B0", "B13", np.nan, "B10", "B12"])
                     A    B
0  2019-03-13 08:12:23   B1
1  2019-03-13 07:10:18   B0
2  2019-03-20 08:12:23  B13
3  2019-03-13 08:12:23  NaN
4  2019-03-15 10:35:53  B10
5  2019-03-20 11:12:23  B12

我想用 B1 填充 NaN 值(B 值发生在同一天,并且在考虑到这个“最大时间”不早于实际 A 列值的条件下具有最长的时间)。

所以我的输出应该是这样的:

                     A    B
0  2019-03-13 08:12:23   B1
1  2019-03-13 07:10:18   B0
2  2019-03-20 08:12:23  B13
3  2019-03-13 08:12:23   B1
4  2019-03-15 10:35:53  B10
5  2019-03-20 11:12:23  B12

我试图实现这一目标但没有成功,我能做的最好的就是使用这个将 NaN 值设为 B13:

df['B']=df['B'].replace('B': 0: np.nan).ffill()

你们能告诉我实现这一目标的最有效和最经济的方法是什么吗?

【问题讨论】:

必须是同一天,还是同一天、同一个月、同一年? @rafaelc 同日、同月、同年 @Arès,您能否在 rafaelc 的回答中查看 cmets 并澄清您所说的“最大时间”是什么意思?是指NaN 被记录之前的最新已知时间吗? 【参考方案1】:

试试groupby().idxmax():

max_val = df.loc[df['A'].groupby(df['A'].dt.date).transform('idxmax'),'B'].values

df['B'] = np.where(df['B'].isna(), max_val, df['B'])

输出:

                    A    B
0 2019-03-13 08:12:23   B1
1 2019-03-13 07:10:18   B0
2 2019-03-20 08:12:23  B13
3 2019-03-13 08:12:23   B1
4 2019-03-15 10:35:53  B10
5 2019-03-20 11:12:23  B12

【讨论】:

【参考方案2】:

使用groupby+ffill

as_date = pd.to_datetime(df.A)
s = np.argsort(as_date)

df['B'] = df.B.loc[s].groupby(as_date.loc[s].dt.date).ffill().loc[df.index]

                     A    B
0  2019-03-13 08:12:23   B1
1  2019-03-13 07:10:18   B0
2  2019-03-20 08:12:23  B13
3  2019-03-13 08:12:23   B1
4  2019-03-15 10:35:53  B10
5  2019-03-20 11:12:23  B12

【讨论】:

这个要求肯定是模棱两可的。我们不知道是否可以提前填充值(OP 应该澄清这一点)。例如,如果这是一个包含股票价格的数据框,您不能将股票价格从 10 AM 回填到 6 AM,因为当时还不知道 感谢大家的参与; 很抱歉碰到这个问题,但是有没有办法让它不仅匹配具有相同年份、月份和日期的行,而且还匹配小时(仅小时)?我尝试使用 dt.time,但显然它也考虑了分钟和秒 @Arès 使用 df.B.loc[s].groupby([as_date.loc[s].dt.date, as_date.loc[s].dt.hour]).ffill().loc[df.index] 或其中的一些内容 谢谢,你这个摇滚老兄!【参考方案3】:

您的任务可以使用以下单线来执行:

df.B = df.sort_values('A').groupby(pd.to_datetime(df.A).dt.date).B.ffill()

【讨论】:

我更正了我最初的解决方案,现在结果还可以。

以上是关于如果行具有相同的“A 列”值,则用最后一个已知值填充空的“B 列”单元格的主要内容,如果未能解决你的问题,请参考以下文章

如果行具有匹配的 ID,则将多行中的值合并为一行(单独的单元格)。如果 ID 只存在一次,则为 NULL 值

如果行在其他列中具有相同的数据,则 SQL 查询 CONCAT/列出唯一列数据?

突出显示 A:B 列中的值相同但 C 列中的值不同的行

如果行中不存在所有值,则插入记录[重复]

Google Script:如果行中的值存在于另一个工作表中,则删除行

如果行中的指定值与条件匹配,则从 CSV 返回一行