【问题标题】:How to generate missing lines in a dataframe如何在数据框中生成缺失的行
【发布时间】:2019-11-04 08:37:03
【问题描述】:

我正在尝试根据年份(整数)在我的数据框中生成缺失的行。我尝试了几种在 stackoverflow 上找到的解决方案,但没有奏效。它返回给我错误:ValueError: cannot reindex from a duplicate axis

Add missing dates to pandas dataframe

Missing data, insert rows in Pandas and fill with NAN

data = {'id': [100, 100, 100, 100, 100, 200, 200], 
    'year':  [2010, 2013, 2014, 2015, 2016, 2010, 2012],
    'value':  [3000, 1000, 2000, 1200, 1300, 2000, 1500]}

df = pd.DataFrame(data) 
df

我在寻找什么

【问题讨论】:

  • 请分享预期的输出以及您尝试过的错误代码
  • 来吧,你不是认真的!是玩游戏吗?我们如何帮助您解决不提供代码且不断变化的问题!

标签: python pandas dataframe


【解决方案1】:

IIUC 你想通过 ID 将数据内插到最大年份范围:

# get the min and max year range
# change max_year if needed
min_year, max_year = df.year.min(), df.year.max()

# for merge
new_df = pd.DataFrame({'year':np.arange(min_year,max_year+1)})

# groupby:
new_df = df.groupby('id').apply(lambda x: new_df.merge(x, how='outer')
                                       .drop('id',axis=1)
                               ).reset_index()

new_df.value.fillna(0, inplace=True)

# this will fill other columns with copies of others
new_df.groupby('id').ffill()

输出:

     id  level_1  year   value
0   100        0  2010  3000.0
1   100        1  2011     0.0
2   100        2  2012     0.0
3   100        3  2013  1000.0
4   100        4  2014  2000.0
5   100        5  2015  1200.0
6   100        6  2016  1300.0
7   200        0  2010  2000.0
8   200        1  2011     0.0
9   200        2  2012  1500.0
10  200        3  2013     0.0
11  200        4  2014     0.0
12  200        5  2015     0.0
13  200        6  2016     0.0

【讨论】:

  • 您的回答很有趣,只是问题是我有其他包含重要信息的列是我不想将其设置为零(只有 value column 必须为零,其他列必须是副本)
  • 那么你可以忽略答案中的fillna。您可以稍后申请fillnaffill
  • 当我忽略 fillna() 时,所有其他列都由 nan 填充。你能更新你的答案吗
  • 当我使用fillna({'value':0, 'no_change': df.no_change}) 时已修复。谢谢。
【解决方案2】:

想法是由DataFrame.set_index 创建MultiIndex 和由MultiIndex 创建的DataFrame.reindexMultiIndex.from_product 创建:

data = {'id': [100, 100, 100, 100, 100, 200, 200], 
    'year':  [2010, 2013, 2014, 2015, 2016, 2010, 2012],
    'value':  [3000, 1000, 2000, 1200, 1300, 2000, 1500]}

df = pd.DataFrame(data) 

#you can specify minimal and maximal year by scalar
mux = pd.MultiIndex.from_product([df['id'].unique(),
                                  np.arange(df['year'].min(), 2019)],
                                  names=['id','year'])

df1 = df.set_index(['id','year']).reindex(mux, fill_value=0).reset_index()
print (df1)
     id  year  value
0   100  2010   3000
1   100  2011      0
2   100  2012      0
3   100  2013   1000
4   100  2014   2000
5   100  2015   1200
6   100  2016   1300
7   100  2017      0
8   100  2018      0
9   200  2010   2000
10  200  2011      0
11  200  2012   1500
12  200  2013      0
13  200  2014      0
14  200  2015      0
15  200  2016      0
16  200  2017      0
17  200  2018      0

#you can specify minimal and maximal year by min and max functions
mux = pd.MultiIndex.from_product([df['id'].unique(),
                                  np.arange(df['year'].min(), df['year'].max() + 1)], 
                                  names=['id','year'])

df2 = df.set_index(['id','year']).reindex(mux, fill_value=0).reset_index()
print (df2)
     id  year  value
0   100  2010   3000
1   100  2011      0
2   100  2012      0
3   100  2013   1000
4   100  2014   2000
5   100  2015   1200
6   100  2016   1300
7   200  2010   2000
8   200  2011      0
9   200  2012   1500
10  200  2013      0
11  200  2014      0
12  200  2015      0
13  200  2016      0

【讨论】:

    【解决方案3】:

    使用 pd.merge_ordered 方法:

    df=pd.DataFrame({'id':(100,100,100,100,100,200,200),'year':(2010,2013,2014,2015,2016,2010,2012),\
                                                            'value':[3000,1000,2000,1200,1300,2000,1500]})
    
    df_year=pd.DataFrame({'year':(2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020)})
    
    
    df_merged=pd.merge_ordered(df,df_year,left_by='id').fillna(0)
    

    【讨论】:

      【解决方案4】:

      使用groupbyreindex()的另一种方法

      l=[g.set_index('year').reindex(range(2010,2019)) for i,g in df.groupby('id')]
      final=pd.concat(l).reset_index()
      final=final.assign(**{'id':final.id.ffill(),'value':final.value.fillna(0)})
      print(final)
      

          year     id   value
      0   2010  100.0  3000.0
      1   2011  100.0     0.0
      2   2012  100.0     0.0
      3   2013  100.0  1000.0
      4   2014  100.0  2000.0
      5   2015  100.0  1200.0
      6   2016  100.0  1300.0
      7   2017  100.0     0.0
      8   2018  100.0     0.0
      9   2010  200.0  2000.0
      10  2011  200.0     0.0
      11  2012  200.0  1500.0
      12  2013  200.0     0.0
      13  2014  200.0     0.0
      14  2015  200.0     0.0
      15  2016  200.0     0.0
      16  2017  200.0     0.0
      17  2018  200.0     0.0
      

      【讨论】:

        【解决方案5】:

        这是一个为“缺失”年份生成行的方法:

        data = {'id': [100, 100, 100, 100, 100, 200, 200], 
            'year':  [2010, 2013, 2014, 2015, 2016, 2010, 2012],
            'value':  [3000, 1000, 2000, 1200, 1300, 2000, 1500]}
        
        df = pd.DataFrame(data) 
        #Pick the existing year extremes
        min_year = df.year.min()
        max_year = df.year.max()
        
        #Look for missing years
        missing_years = [x for x in range(min_year, max_year+1) if x not in df.year.values]
        
        #Generate a dataframe
        df_missing =  pd.DataFrame([[None, x, None] for x in missing_years], columns = df.columns)
        
        #Append it to original 
        df.append(df_missing)
        

        输出

        +----+-------+-------+-------+
        |    |  id   | year  | value |
        +----+-------+-------+-------+
        | 0  | 100   | 2010  | 3000  |
        | 1  | 100   | 2013  | 1000  |
        | 2  | 100   | 2014  | 2000  |
        | 3  | 100   | 2015  | 1200  |
        | 4  | 100   | 2016  | 1300  |
        | 5  | 200   | 2010  | 2000  |
        | 6  | 200   | 2012  | 1500  |
        | 0  | None  | 2011  | None  |
        +----+-------+-------+-------+
        

        【讨论】:

          【解决方案6】:
          import datetime
          import pandas as pd
          year = datetime.datetime.today().year #Today date(year)
          
          data = {'id': [100, 100, 100, 100, 100, 200, 200], 
              'year':  [2010, 2013, 2014, 2015, 2016, 2010, 2012],
              'value':  [3000, 1000, 2000, 1200, 1300, 2000, 1500]}
          
          df = pd.DataFrame(data)
          min = df['year'].min() #Find min year in data's
          
          difference = year-min
          years = range(year, year -difference , -1)
          
          data['year'] = years
          
          df = pd.DataFrame.from_dict(data, orient='index') #When we add years,it gives an error 'arrays must all be same length' so avoid it with adding 'Nan
          df.transpose()
          print df
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-08-22
            • 1970-01-01
            • 2016-11-10
            • 2017-02-19
            • 1970-01-01
            • 1970-01-01
            • 2021-12-23
            • 2021-10-22
            相关资源
            最近更新 更多