【问题标题】:Fill in missing pandas data with previous non-missing value, grouped by key用之前的非缺失值填充缺失的 pandas 数据,按 key 分组
【发布时间】:2013-04-27 01:41:21
【问题描述】:

我正在处理这样的熊猫数据帧:

   id    x
0   1   10
1   1   20
2   2  100
3   2  200
4   1  NaN
5   2  NaN
6   1  300
7   1  NaN

我想用具有相同 'id' 值的行中的前一个非 NAN 'x' 替换每个 NAN 'x':

   id    x
0   1   10
1   1   20
2   2  100
3   2  200
4   1   20
5   2  200
6   1  300
7   1  300

是否有一些巧妙的方法可以在不手动循环行的情况下做到这一点?

【问题讨论】:

    标签: python pandas nan missing-data data-cleaning


    【解决方案1】:

    您可以对每个组执行groupby/forward-fill 操作:

    import numpy as np
    import pandas as pd
    
    df = pd.DataFrame({'id': [1,1,2,2,1,2,1,1], 'x':[10,20,100,200,np.nan,np.nan,300,np.nan]})
    df['x'] = df.groupby(['id'])['x'].ffill()
    print(df)
    

    产量

       id      x
    0   1   10.0
    1   1   20.0
    2   2  100.0
    3   2  200.0
    4   1   20.0
    5   2  200.0
    6   1  300.0
    7   1  300.0
    

    【讨论】:

    • “填充”选项是我需要的。谢谢!
    • 您也可以使用df['x'] = df.groupby('id').fillna(method='ffill') 来实现同样的效果,语法稍简单。
    • @Zhang18:感谢改进。 df.groupby(['id']).ffill() 也可以。
    【解决方案2】:
    df
       id   val
    0   1   23.0
    1   1   NaN
    2   1   NaN
    3   2   NaN
    4   2   34.0
    5   2   NaN
    6   3   2.0
    7   3   NaN
    8   3   NaN
    
    df.sort_values(['id','val']).groupby('id').ffill()
    
        id  val
    0   1   23.0
    1   1   23.0
    2   1   23.0
    4   2   34.0
    3   2   34.0
    5   2   34.0
    6   3   2.0
    7   3   2.0
    8   3   2.0
    

    使用 sort_values、groupby 和 ffill,这样如果您有 Nan 值作为第一个值或一组第一个值,它们也会被填充。

    【讨论】:

      【解决方案3】:

      多键问题的解决方案:

      在此示例中,数据具有键 [日期、地区、类型]。 Date 是原始数据帧上的索引。

      import os
      import pandas as pd
      
      #sort to make indexing faster
      df.sort_values(by=['date','region','type'], inplace=True)
      
      #collect all possible regions and types
      regions = list(set(df['region']))
      types = list(set(df['type']))
      
      #record column names
      df_cols = df.columns
      
      #delete ffill_df.csv so we can begin anew
      try:
          os.remove('ffill_df.csv')
      except FileNotFoundError:
          pass
      
      # steps:
      # 1) grab rows with a particular region and type
      # 2) use forwardfill to fill nulls
      # 3) use backwardfill to fill remaining nulls
      # 4) append to file
      for r in regions:
          for t in types:
              group_df = df[(df.region == r) & (df.type == t)].copy()
              group_df.fillna(method='ffill', inplace=True)
              group_df.fillna(method='bfill', inplace=True)
              group_df.to_csv('ffill_df.csv', mode='a', header=False, index=True) 
      

      检查结果:

      #load in the ffill_df
      ffill_df = pd.read_csv('ffill_df.csv', header=None, index_col=None)
      ffill_df.columns = df_reindexed_cols
      ffill_df.index= ffill_df.date
      ffill_df.drop('date', axis=1, inplace=True)
      ffill_df.head()
      
      #compare new and old dataframe
      print(df.shape)        
      print(ffill_df.shape)
      print()
      print(pd.isnull(ffill_df).sum())
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-28
        • 2022-11-02
        • 1970-01-01
        • 2019-11-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多