Генерация непрерывной серии отсутствующих месяцев за год для данных в pandas

#python #python-3.x #pandas #dataframe

#python #python-3.x #pandas #dataframe

Вопрос:

Вот данные. Для каждого человека это дает денежный вклад, который они внесли за этот месяц:

     df.head()

    | year_mo | name  | contribution|
    | 202001  | Fey   |  30         |
    | 202003  | Fey   |  20         |
    | 202004  | Fey   |  10         |
    | 202001  | Jay   |  30         |
    | 202003  | Jay   |  20         |
  

Я хочу сгенерировать непрерывную серию year_mo для каждого пользователя с 202001 по 202006 год, где, если бы человек не внес свой вклад, это было бы 0, как это :

     | year_mo | name  | contribution|
    | 202001  | Fey   |  30         |
    | 202002  | Fey   |   0         |
    | 202003  | Fey   |  20         |
    | 202004  | Fey   |  10         |
    | 202005  | Fey   |   0         |
    | 202006  | Fey   |   0         |
    | 202001  | Jay   |  30         |
    | 202002  | Jay   |   0         |
    | 202003  | Jay   |  20         |
    | 202004  | Jay   |   0         |
    | 202005  | Jay   |   0         |
    | 202006  | Jay   |   0         |
  

Чтобы сделать это, когда я пытался выполнить внешнее соединение с непрерывным годом месяц df, я попробовал следующее, но не получил желаемого результата:

    years = list(range(2020,2021,1))
   months= list(range(1,7,1))
   rows_list = []


   for yr in years:
     for mn in months:
     dict1 = {}
     dict1 = {'key' :1, 'year_mo' : (yr*100) mn}
     rows_list.append(dict1)
   yearmo_df = pd.DataFrame(rows_list)
 
   df['key'] = 1

 
   new_df = pd.merge(left=df, right=yearmo_df, left_on='year_mo' ,right_on='year_mo', how='outer')
  

Ответ №1:

Мы можем использовать MultiIndex и reindex :

 new_idx = pd.MultiIndex.from_product([np.arange(202001,202007), df['name'].unique()],
                                     names=['year_mo','name'])

(df.set_index(['year_mo', 'name'])
   .reindex(new_idx, fill_value=0)
   .sort_index(level=['name','year_mo'])
   .reset_index()
)
  

За другим optino pivot_table следует re_index , и stack :

 (df.pivot_table(index='year_mo', columns='name', fill_value=0)
   .reindex(np.arange(202001,202007), fill_value=0)
   .stack()
   .reset_index()
)
  

Вывод:

     year_mo name  contribution
0    202001  Fey            30
1    202002  Fey             0
2    202003  Fey            20
3    202004  Fey            10
4    202005  Fey             0
5    202006  Fey             0
6    202001  Jay            30
7    202002  Jay             0
8    202003  Jay            20
9    202004  Jay             0
10   202005  Jay             0
11   202006  Jay             0