【问题标题】:How to convert monthy data to nan based on a condition?如何根据条件将月度数据转换为 nan?
【发布时间】:2021-03-24 06:34:59
【问题描述】:

我有这个 df:

       CODE      DATE     TMAX  TMIN   PP
0      000130 1991-01-01  32.6  23.4  0.0
1      000130 1991-01-02  31.2  22.4  0.0
2      000130 1991-01-03  32.0   NaN  0.0
3      000130 1991-01-04  32.2  23.0  0.0
4      000130 1991-01-05  30.5  22.0  0.0
      ...        ...   ...   ...  ...
10865  000130 2020-12-31   NaN   NaN  NaN
10866  000132 1991-01-01  35.2   NaN  0.0
10867  000132 1991-01-02  34.6   NaN  0.0
10868  000132 1991-01-03  35.8   NaN  0.0
10869  000132 1991-01-04  34.8   NaN  0.0

仅当一个月内有 5 个或更多连续 NaN 值时,我才想将月度数据转换为 NaN。

例如:如果 1991 年 1 月在 TMAX 列中有 5 个或更多连续的 NaN 值,则必须将 1991 年 1 月 TMAX 列的所有值转换为 NaN。每年的每个月都一样。我需要通过 CODE 执行此操作(每个 CODE 值都有 1991 年 1 月、1991 年 2 月、... 2020 年 12 月的 TMAX 数据)。所以我首先考虑使用df.groupby['CODE']。有371个代码。

对于 PP 列,仅当一个月中有 3 个或更多非连续 NaN 值时,我才需要将月度数据转换为 NaN。例如:如果 1991 年 1 月在 PP 列中有 3 个非连续 NaN 值,则必须将 1991 年 1 月 TMAX 列的所有值转换为 NaN。每年的每个月都一样。我也需要通过 CODE 来完成。

我是 python 初学者,所以我将不胜感激。

提前致谢。

【问题讨论】:

    标签: pandas


    【解决方案1】:
    • identifying consecutive NaNs
    • 生成测试数据集的合理代码量
    • 定义要在transform()中调用的函数
    • groupby() CODE, year & month 调用函数
    • n 是一个参数,因此可用于不同的连续运行
    # contruct a CODE / DATE dataframe
    df = (pd.DataFrame([f"{i:08d}" for i in range(3)], columns=["CODE"]).assign(foo=1)
     .merge(pd.DataFrame(pd.date_range("01-Jan-1991", "01-Jan-1993"), columns=["DATE"]).assign(foo=1), on="foo")
     .drop(columns="foo")
    )
    
    
    # add a column that has NaNs in it, some will consequetive...
    A = np.random.uniform(20,30, len(df))
    A.ravel()[np.random.choice(A.size, A.size//3, replace=False)] = np.nan
    df["TMIN"] = A
    
    # function that will return NaN if more than n consecutive NaNs
    def consecutivenan(d, n=5):
        if d.isnull().astype(int).groupby(d.notnull().astype(int).cumsum()).sum().ge(n).any():
            return np.nan 
        else:
            return d
    
    df["TMIN_C"] = df.groupby(["CODE", df.DATE.dt.year, df.DATE.dt.month], as_index=False)["TMIN"].transform(consecutivenan, n=5)
    
    # demo it's worked
    i = df.loc[~df.TMIN.isna() & df.TMIN.ne(df.TMIN_C)].index[0]
    df.loc[i-2:i+28]
    
    
    

    输出

    有 5 个连续的 NaN 值,因此整月已设置为 NaN

    CODE DATE TMIN TMIN_C
    271 00000000 1991-09-29 00:00:00 28.1745 28.1745
    272 00000000 1991-09-30 00:00:00 21.1691 21.1691
    273 00000000 1991-10-01 00:00:00 28.7848 nan
    274 00000000 1991-10-02 00:00:00 22.2346 nan
    275 00000000 1991-10-03 00:00:00 22.306 nan
    276 00000000 1991-10-04 00:00:00 21.5774 nan
    277 00000000 1991-10-05 00:00:00 23.8348 nan
    278 00000000 1991-10-06 00:00:00 21.4416 nan
    279 00000000 1991-10-07 00:00:00 nan nan
    280 00000000 1991-10-08 00:00:00 nan nan
    281 00000000 1991-10-09 00:00:00 nan nan
    282 00000000 1991-10-10 00:00:00 27.3833 nan
    283 00000000 1991-10-11 00:00:00 27.2125 nan
    284 00000000 1991-10-12 00:00:00 nan nan
    285 00000000 1991-10-13 00:00:00 nan nan
    286 00000000 1991-10-14 00:00:00 nan nan
    287 00000000 1991-10-15 00:00:00 nan nan
    288 00000000 1991-10-16 00:00:00 nan nan
    289 00000000 1991-10-17 00:00:00 24.8782 nan
    290 00000000 1991-10-18 00:00:00 29.7879 nan
    291 00000000 1991-10-19 00:00:00 27.0532 nan
    292 00000000 1991-10-20 00:00:00 21.3854 nan
    293 00000000 1991-10-21 00:00:00 nan nan
    294 00000000 1991-10-22 00:00:00 nan nan
    295 00000000 1991-10-23 00:00:00 23.6399 nan
    296 00000000 1991-10-24 00:00:00 nan nan
    297 00000000 1991-10-25 00:00:00 24.7265 nan
    298 00000000 1991-10-26 00:00:00 20.2296 nan
    299 00000000 1991-10-27 00:00:00 22.0885 nan
    300 00000000 1991-10-28 00:00:00 27.3212 nan
    301 00000000 1991-10-29 00:00:00 nan nan

    【讨论】:

      猜你喜欢
      • 2019-12-06
      • 2023-01-26
      • 1970-01-01
      • 2020-08-28
      • 2015-11-01
      • 1970-01-01
      • 2021-10-14
      • 2018-04-12
      • 2017-03-22
      相关资源
      最近更新 更多