добавить значение строки, если не существует группы по дате

pandas

#pandas

Вопрос:

у меня есть фрейм данных ниже, я хочу убедиться, что если значение ELSE не существует в столбце, я должен его добавить.

мой источник фрейма данных приведен ниже

 date         zone       RATE
2021-09-01    NY        90
2021-09-01    LA        80
2021-09-01    ELSE      10
2021-09-02    NY        60
2021-09-02    LA        70
 

ожидаемый результат

 2021-09-01    NY        90
2021-09-01    LA        80
2021-09-01    ELSE      10
2021-09-02    NY        60
2021-09-02    LA        70
2021-09-02    ELSE      0
 

Ответ №1:

Использовать DataFrame.unstack с DataFrame.stack , для исходного порядка используется упорядоченный Categorical :

 df['zone'] = pd.Categorical(df['zone'], ordered=True, categories=df['zone'].unique())

df = df.set_index(['date','zone']).unstack(fill_value=0).stack().reset_index()
print (df)
         date  zone  RATE
0  2021-09-01    NY    90
1  2021-09-01    LA    80
2  2021-09-01  ELSE    10
3  2021-09-02    NY    60
4  2021-09-02    LA    70
5  2021-09-02  ELSE     0
 

Альтернатива:

 df['zone'] = pd.Categorical(df['zone'], ordered=True, categories=df['zone'].unique())

df = df.set_index(['date','zone'])
df = df.reindex(pd.MultiIndex.from_product(df.index.levels), fill_value=0).reset_index()
print (df)

         date  zone  RATE
0  2021-09-01    NY    90
1  2021-09-01    LA    80
2  2021-09-01  ELSE    10
3  2021-09-02    NY    60
4  2021-09-02    LA    70
5  2021-09-02  ELSE     0
 

Или:

 from  itertools import product

df1 = pd.DataFrame(product(df['date'].unique(), df['zone'].unique()), 
                   columns=['date','zone'])
df = df1.merge(df, how='left').fillna({'RATE':0}).astype({'RATE':int})
print (df)

         date  zone  RATE
0  2021-09-01    NY    90
1  2021-09-01    LA    80
2  2021-09-01  ELSE    10
3  2021-09-02    NY    60
4  2021-09-02    LA    70
5  2021-09-02  ELSE     0
 

Комментарии:

1. У меня есть только один вопрос со стороны ~ pivot и unstack, похоже, сортируют столбцы самостоятельно, верно ~

2. спасибо @jezrael я хочу соблюдать тот же порядок, Нью-Йорк, Лос-Анджелес, тогда ЕЩЕ? пожалуйста?

Ответ №2:

Выполните pivot тогда fillna и stack обратно

 out = df.pivot(*df.columns).fillna(0).stack().reset_index(name='RATE')
Out[437]: 
        date  zone  RATE
0 2021-09-01  ELSE  10.0
1 2021-09-01    LA  80.0
2 2021-09-01    NY  90.0
3 2021-09-02  ELSE   0.0
4 2021-09-02    LA  70.0
5 2021-09-02    NY  60.0