Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python pandas数据帧使用一年中的离散天数窗口使用groupby为NAN插值_Python_Pandas - Fatal编程技术网

Python pandas数据帧使用一年中的离散天数窗口使用groupby为NAN插值

Python pandas数据帧使用一年中的离散天数窗口使用groupby为NAN插值,python,pandas,Python,Pandas,下面的小型可再现示例设置了一个长度为100年的数据帧,其中包含一些随机生成的值。然后插入3个100天的缺失值。使用这个小示例,我试图整理pandas命令,这些命令将使用一年中某一天的平均值(因此使用.groupby)和条件来填充缺少的天数。例如,如果缺少4月12日,如何更改最后一行代码,以便仅使用10个最接近的4月12日来填充缺少的值?换句话说,1920年缺失的4月12日值将使用1915年至1925年之间的平均4月12日值进行填充;2000年缺少的April 12th值将用1995年到2005年

下面的小型可再现示例设置了一个长度为100年的数据帧,其中包含一些随机生成的值。然后插入3个100天的缺失值。使用这个小示例,我试图整理pandas命令,这些命令将使用一年中某一天的平均值(因此使用.groupby)和条件来填充缺少的天数。例如,如果缺少4月12日,如何更改最后一行代码,以便仅使用10个最接近的4月12日来填充缺少的值?换句话说,1920年缺失的4月12日值将使用1915年至1925年之间的平均4月12日值进行填充;2000年缺少的April 12th值将用1995年到2005年之间的平均April 12th值填充,等等。我尝试在脚本的最后一行向lambda函数添加.rolling(),但尝试失败

奖金问题:下面的例子从1918年延续到2018年。例如,如果在1919年4月12日缺少一个值,那么如果使用4月12日的10个值来填充缺少的值仍然是很好的,即使窗口不能“居中”于缺少的日期,因为它接近时间序列的开始。对于上面的第一个问题,是否有一个足够灵活的解决方案,当缺少的值接近时间序列的开始和结束时,仍然使用至少10个值

import pandas as pd
import numpy as np
import random

# create 100 yr time series
dates = pd.date_range(start="1918-01-01", end="2018-12-31").strftime("%Y-%m-%d")
vals = [random.randrange(1, 50, 1) for i in range(len(dates))]
# Create some arbitrary gaps
vals[100:200] = vals[9962:10062] = vals[35895:35995] = [np.nan] * 100

# Create dataframe
df = pd.DataFrame(dict(                                                   
    list(                                                                 
        zip(["Date", "vals"],                                              
            [dates, vals])                                 
        )                                                                 
))  

# confirm missing vals
df.iloc[95:105]
df.iloc[35890:35900]

# set a date index (for use by groupby)
df.index = pd.DatetimeIndex(df['Date'])
df['Date'] = df.index

# Need help restricting the mean to the 10 nearest same-days-of-the-year:
df['vals'] = df.groupby([df.index.month, df.index.day])['vals'].transform(lambda x: x.fillna(x.mean()))

我不确定我对你问题的意图了解到了什么程度。我采取的方法是满足两个要求

  • 需要任意数量的平均值
  • 使用这些平均值填写NA
  • 我已向大会发言 简单地说,我不是用日期前后来填写NA,而是用从连续任意年份中提取的平均值来填写NA

    import pandas as pd
    import numpy as np
    import random
    
    # create 100 yr time series
    dates = pd.date_range(start="1918-01-01", end="2018-12-31").strftime("%Y-%m-%d")
    vals = [random.randrange(1, 50, 1) for i in range(len(dates))]
    # Create some arbitrary gaps
    vals[100:200] = vals[9962:10062] = vals[35895:35995] = [np.nan] * 100
    
    # Create dataframe
    df = pd.DataFrame(dict(                                                   
        list(                                                                 
            zip(["Date", "vals"],                                              
                [dates, vals])                                 
            )                                                                 
    ))  
    
    df['Date'] = pd.to_datetime(df['Date'])
    df['mm-dd'] = df['Date'].apply(lambda x:'{:02}-{:02}'.format(x.month, x.day))
    df['yyyy'] = df['Date'].apply(lambda x:'{:04}'.format(x.year))
    df = df.iloc[:,1:].pivot(index='mm-dd', columns='yyyy')
    df.columns = df.columns.droplevel(0)
    df['nans'] = df.isnull().sum(axis=1)
    df['10n_mean'] = df.iloc[:,:-1].sample(n=10, axis=1).mean(axis=1)
    df['10n_mean'] = df['10n_mean'].round(1)
    
    df.loc[df['nans'] >= 1]
    yyyy    1918    1919    1920    1921    1922    1923    1924    1925    1926    1927    ...     2011    2012    2013    2014    2015    2016    2017    2018    nans    10n_mean
    mm-dd                                                                                   
    02-29   NaN     NaN     34.0    NaN     NaN     NaN     2.0     NaN     NaN     NaN     ...     NaN     49.0    NaN     NaN     NaN     32.0    NaN     NaN     76  21.6
    04-11   NaN     43.0    12.0    28.0    29.0    28.0    1.0     38.0    11.0    3.0     ...     17.0    35.0    8.0     17.0    34.0    NaN     5.0     33.0    3   29.7
    04-12   NaN     19.0    38.0    34.0    48.0    46.0    28.0    29.0    29.0    14.0    ...     41.0    16.0    9.0     39.0    8.0     NaN     1.0     12.0    3   21.3
    04-13   NaN     33.0    26.0    47.0    21.0    26.0    20.0    16.0    11.0    7.0     ...     5.0     11.0    34.0    28.0    27.0    NaN     2.0     46.0    3   21.3
    04-14   NaN     36.0    19.0    6.0     45.0    41.0    24.0    39.0    1.0     11.0    ...     30.0    47.0    45.0    14.0    48.0    NaN     16.0    8.0     3   24.7
    
    df_mean = df.T.fillna(df['10n_mean'], downcast='infer').T
    df_mean.loc[df_mean['nans'] >= 1]
    yyyy    1918    1919    1920    1921    1922    1923    1924    1925    1926    1927    ...     2011    2012    2013    2014    2015    2016    2017    2018    nans    10n_mean
    mm-dd                                                                                   
    02-29   21.6    21.6    34.0    21.6    21.6    21.6    2.0     21.6    21.6    21.6    ...     21.6    49.0    21.6    21.6    21.6    32.0    21.6    21.6    76.0    21.6
    04-11   29.7    43.0    12.0    28.0    29.0    28.0    1.0     38.0    11.0    3.0     ...     17.0    35.0    8.0     17.0    34.0    29.7    5.0     33.0    3.0     29.7
    04-12   21.3    19.0    38.0    34.0    48.0    46.0    28.0    29.0    29.0    14.0    ...     41.0    16.0    9.0     39.0    8.0     21.3    1.0     12.0    3.0     21.3
    04-13   21.3    33.0    26.0    47.0    21.0    26.0    20.0    16.0    11.0    7.0     ...     5.0     11.0    34.0    28.0    27.0    21.3    2.0     46.0    3.0     21.3
    04-14   24.7    36.0    19.0    6.0     45.0    41.0    24.0    39.0    1.0     11.0    ...     30.0    47.0    45.0    14.0    48.0    24.7    16.0    8.0     3.0     24.7
    

    这两部分都能回答

    • 构建一个DF
      dfr
      ,这是您想要的计算
    • lambda
      函数返回一个dict
      {year:val,…}
    • 确保以合理的方式命名索引
    • apply(pd.Series)
    • 通过将年份列放回索引中来重塑
    • merge()
      使用原始DF构建DFVAL列包含
      NaN
      0列是要填充的值
    • 最后
      fillna()
    分析
    • 以1918年4月11日的NaN为例,违约率为22,因为它是从1921年开始回填的
    • (12+2+47+47+2)/5==22
    键0 钥匙1 键2 日期 瓦尔斯 0 100 4. 11 1918 1918-04-11 00:00:00 楠 22 465 4. 11 1919 1919-04-11 00:00:00 12 22 831 4. 11 1920 1920-04-11 00:00:00 2. 22 1196 4. 11 1921 1921-04-11 00:00:00 47 27 1561 4. 11 1922 1922-04-11 00:00:00 47 36 1926 4. 11 1923 1923-04-11 00:00:00 2. 34.6 2292 4. 11 1924 1924-04-11 00:00:00 37 29.4
    如果你的NA不是太多,也就是说,速度不令人担忧,试试这个基本上循环通过所有的NAN和排序(按年的距离),得到头10
    # create 100 yr time series
    dates = pd.date_range(start="1918-01-01", end="2018-12-31")
    vals = [random.randrange(1, 50, 1) for i in range(len(dates))]
    # Create some arbitrary gaps
    vals[100:200] = vals[9962:10062] = vals[35895:35995] = [np.nan] * 100
    
    # Create dataframe - simplified from question...
    df = pd.DataFrame({"Date":dates,"vals":vals})  
    
    df[df.isna().any(axis=1)]
    
    ystart = df.Date.dt.year.min()
    # generate rolling means for month/day.  bfill for when it's start of series
    dfr = (df.groupby([df.Date.dt.month, df.Date.dt.day])["vals"]
     .agg(lambda s: {y+ystart:v for y,v in enumerate(s.dropna().rolling(5).mean().bfill())})
     .to_frame().rename_axis(["month","day"])
    )
    
    # expand dict into columns and reshape to by indexed by month,day,year
    dfr = dfr.join(dfr.vals.apply(pd.Series)).drop(columns="vals").rename_axis("year",axis=1).stack().to_frame()
    
    # get df index back, plus vals & fillna (column 0) can be seen alongside each other
    dfm = df.merge(dfr, left_on=[df.Date.dt.month,df.Date.dt.day,df.Date.dt.year], right_index=True)
    
    # finally what we really want to do - fill tha NaNs
    df.fillna(dfm[0])
    
    
    dfm.query("key_0==4 & key_1==11").head(7)