使用Pandas进行采样和保持

mrwjdhj3  于 2023-03-21  发布在  其他
关注(0)|答案(1)|浏览(120)

我有一个Pandas Dataframe ,看起来像这样
| | 识别号|时间|价值|
| - ------|- ------|- ------|- ------|
| 无|1个|十个|1.0分|
| 1个|第二章|十个|2.0版|
| 第二章|1个|二十个|钠氮|
| 三个|三个|二十个|4.0版|
| 四个|1个|三十|钠氮|
| 五个|第二章|三十|钠氮|
| 六个|四个|三十|钠氮|
我想对每个ID进行采样和保持,使用最后一个已知的非空值来基于参数max_time估算一些空值。对于Value为空且时间为t的每一行,如果有一行具有相同的ID和时间t_other,例如t-max_time <= t_other <= t,然后我想用满足这个约束的最大值t_other的行的Value替换我的行的Value
例如,在上面的表格中,如果max_time=10,那么对于Time = 20处的ID = 1,我们有一个空值Value,可以用Time = 10处的值来填充。
| | 识别号|时间|价值|
| - ------|- ------|- ------|- ------|
| 无|1个|十个|1.0分|
| 1个|第二章|十个|2.0版|
| 第二章|1个|二十个|1.0分|
| 三个|三个|二十个|4.0版|
| 四个|1个|三十|钠氮|
| 五个|第二章|三十|钠氮|
| 六个|四个|三十|钠氮|
其他空值在最后10个时间单位中没有值,无法填充它们,因此它们保持为空值。
我问了ChatGPT,它给出了解决方案

def fill_nulls(group):
    # Fill nulls with the last non-null value
    group['Value'] = group['Value'].ffill()
    
    # Calculate the time difference between consecutive rows
    time_diff = group['Time'].diff()
    
    # Set nulls to NaN if the time difference is greater than 10
    group['Value'][time_diff > 10] = np.nan

    return group

filled_df = df.groupby('ID').apply(fill_nulls)

但这是使用行索引2被填充的事实来表示行索引4不应该被替换为null,并且在那里也填充1.0,这不是我想要的。
我认为最好的方法是填充所有行,并将不应该填充的行替换为null,就像ChatGPT尝试的那样,但我不知道如何编写哪些行应该替换为null的逻辑。

z0qdvdin

z0qdvdin1#

您可以使用布尔掩码和merge

max_time = 10

m = df['Value'].isna()
vals = (df[m].reset_index().merge(df[~m], on='ID')
             .query('Time_x - Time_y <= @max_time')
             .drop_duplicates('index', keep='last')
             .set_index('index')['Value_y'])
df['Value'] = df['Value'].fillna(vals)

输出:

>>> df
   ID  Time  Value
0   1    10    1.0
1   2    10    2.0
2   1    11    1.1  # <- ADDED
3   1    20    1.1  # <- FILLED
4   3    20    4.0
5   1    30    NaN
6   2    30    NaN
7   4    30    NaN

相关问题