Нужно сохранить значения NaN при изменении формы кадра данных.

Эти два вопроса могут быть связаны:

Но не смог использовать предоставленные ответы - могу ли я как-то установить счетчик минут для np.sum?

import pandas as pd
import numpy as np
df = pd.DataFrame([['Y1', np.nan], ['Y2', np.nan], ['Y1', 6], ['Y2',8]], columns=['A', 'B'], index=['1988-01-01','1988-01-01', '1988-01-04', '1988-01-04'])
df.index.name = 'Date'
df

pivot_df = pd.pivot_table(df, values='B', index=['Date'], columns=['A'],aggfunc=np.sum)
pivot_df

Выход:

A   Y1  Y2
Date        
1988-01-01  0.0 0.0
1988-01-04  6.0 8.0

И желаемый результат:

A   Y1  Y2
Date        
1988-01-01  NaN NaN
1988-01-04  6.0 8.0
2
Henrik K 4 Июл 2019 в 17:32

5 ответов

Лучший ответ

Если у вас нет повторяющихся записей, используйте set_index + unstack

df.set_index('A', append=True)['B'].unstack(-1)
A            Y1   Y2
Date
1988-01-01  NaN  NaN
1988-01-04  6.0  8.0

Если у вас есть дубликаты, используйте groupby с min_count

>> df

             A    B
Date
1988-01-01  Y1  NaN
1988-01-01  Y2  NaN
1988-01-04  Y1  6.0
1988-01-04  Y2  8.0
1988-01-01  Y1  NaN
1988-01-01  Y2  NaN
1988-01-04  Y1  6.0
1988-01-04  Y2  8.0
df.set_index('A', append=True).groupby(level=[0, 1])['B'].sum(min_count=1).unstack(-1)
A             Y1    Y2
Date
1988-01-01   NaN   NaN
1988-01-04  12.0  16.0
1
user3483203 4 Июл 2019 в 14:52

Из полезных комментариев следующее решение отвечает моим требованиям:


pivot_df_2 = pd.pivot_table(df, values='B', index=['Date'], columns=['A'],aggfunc=min, dropna=False)
pivot_df_2

Значения должны быть уникальными для каждого слота, поэтому замена функции sum на функцию min не должна иметь значения (в моем случае)

1
Henrik K 4 Июл 2019 в 14:44

Можно посчитать значения и сбросить, когда 0 (или меньше ожидаемого значения):

pivot_df = pd.pivot_table(df, values='B', index=['Date'], columns=['A'],
                          aggfunc=['sum','count'])

# build the mask from count
mask = (pivot_df.xs('count', axis=1) == 0)   # or ...<min_limit

#build the actual pivot_df from sum
pivot_df = pivot_df.xs('sum', axis=1)

# and reset to NaN when not enough values
pivot_df[mask] = np.nan

Это дает, как и ожидалось:

A            Y1   Y2
Date                
1988-01-01  NaN  NaN
1988-01-04  6.0  8.0

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

1
Serge Ballesta 4 Июл 2019 в 14:50

В этом случае я бы разрешил groupby:

(df.groupby(['Date', 'A']).B
   .apply(lambda x: np.nan if x.isna().all() else x.sum())
   .unstack('A')
)

Выход:

A            Y1   Y2
Date                
1988-01-01  NaN  NaN
1988-01-04  6.0  8.0

Замените isna().all() на isna().any(), если это необходимо.

1
Quang Hoang 4 Июл 2019 в 14:42

Попробуйте добавить 'dropna= False' к вашей функции сводной таблицы?

1
Akber Iqbal 20 Дек 2019 в 03:30