如何结合Pandas resample与nsmallest按日期提取各列第二小值?
如何结合resample与nsmallest提取每日第二小值
嘿,这个需求我熟,咱们一步步来搞定它!首先先把你的示例数据转换成可操作的DataFrame,方便后续演示:
import pandas as pd # 构造你的示例数据 data = [ ["2020-01-07 09:00:00",22,228], ["2020-01-07 10:00:00",22,228], ["2020-01-07 11:00:00",22,228], ["2020-01-07 12:00:00",22,228], ["2020-01-07 13:00:00",22,228], ["2020-01-07 14:00:00",22,228], ["2020-01-07 15:00:00",21,228], ["2020-01-07 16:00:00",22,228], ["2020-01-08 09:00:00",43,45], ["2020-01-08 10:00:00",44,45], ["2020-01-08 11:00:00",41,45], ["2020-01-08 12:00:00",47,43] ] df = pd.DataFrame(data, columns=["DateTime", "Col1", "Col2"]) df["DateTime"] = pd.to_datetime(df["DateTime"])
核心思路是按日期分组(resample)后,对每个分组的每一列提取第2小的值,这里有两种简洁的实现方式:
方法一:resample + apply 链式处理
我们可以对resample后的每个组,直接用apply调用nsmallest(2)取前2小值,再取最后一个(也就是第二小的,因为nsmallest会按升序排列):
# 按天重采样,提取每列第二小值 second_smallest = df.resample('D', on='DateTime').apply(lambda x: x.nsmallest(2).iloc[-1]) print(second_smallest)
代码解释
resample('D', on='DateTime'):按自然天对数据分组,指定DateTime列为时间依据lambda x: x.nsmallest(2).iloc[-1]:对每个分组的每一列,先筛选出前2小的行,再取最后一行。如果某列当天所有值都相同,nsmallest(2)会返回两个重复值,取最后一个还是同一个值,完全符合预期。
方法二:resample + agg 自定义函数(可读性更强)
如果需要处理边界情况(比如某天只有1条数据),可以写个自定义函数,用agg方法统一处理:
def get_second_smallest(series): # 处理边界:如果当天数据不足2条,返回唯一值;否则返回第二小值 return series.nsmallest(2).iloc[-1] if len(series) >= 2 else series.iloc[0] second_smallest = df.resample('D', on='DateTime').agg(get_second_smallest) print(second_smallest)
输出结果
两种方法都会得到如下结果:
Col1 Col2 DateTime 2020-01-07 22 228 2020-01-08 43 45
验证一下:
- 2020-01-07的Col1最小值是21,第二小是22;Col2全为228,所以第二小也是228
- 2020-01-08的Col1排序后是41、43,第二小是43;Col2排序后是43、45,第二小是45,完全符合你的需求!
内容的提问来源于stack exchange,提问作者The Ref
相关产品推荐
相关产品推荐

