У меня есть следующий фрейм данных:
data = {'a': {1: None, 2: 1, 3: 7, 4: 2, 5: 4},
'b': {1: None, 2: 2, 3: 2, 4: 9, 5: 6},
'c': {1: None, 2: 2.0, 3: None, 4: 7.0, 5: 4.0}}
df = pd.DataFrame(data).rename_axis('day')
a b c
day
1 NaN NaN NaN
2 1.0 2.0 2.0
3 7.0 2.0 NaN
4 2.0 9.0 7.0
5 4.0 6.0 4.0
Я хочу получить новый столбец («std») со стандартным отклонением всех значений столбца. NaN следует игнорировать. Допустим, количество строк, которые должны быть включены в скользящее окно, равно 3, а min_ periods (то есть количество строк хотя бы с одним ненулевым значением) равно 2.
Это ожидаемый результат:
a b c std
day
1 NaN NaN NaN NaN
2 1.0 2.0 2.0 NaN
3 7.0 2.0 NaN 2.387467
4 2.0 9.0 7.0 3.116775
5 4.0 6.0 4.0 2.531939
Первое стандартное значение (2,387467) равно np.std ([1,2,2,7,2], ddof=1).
Я попробовал оба предложенных решения здесь, но они не работают должным образом с моим фреймом данных, вероятно, из-за NaN.
Вы можете использовать numpy.nanstd для работы с пропущенными значениями:
#source https://stackoverflow.com/a/77704074/2901002
from numpy.lib.stride_tricks import sliding_window_view as swv
N = 3
df.loc[df.index[N-1:], 'std'] = np.nanstd(swv(df.to_numpy(), N, axis=0), (1,2), ddof=1)
print (df)
a b c std
day
1 NaN NaN NaN NaN
2 1.0 2.0 2.0 NaN
3 7.0 2.0 NaN 2.387467
4 2.0 9.0 7.0 3.116775
5 4.0 6.0 4.0 2.531939
@younggotti — это параметр axis=(1,2)
в numpy.nanstd, причина в том, что обработка 3D array
Другое решение:
def fn(idx):
g = df.loc[idx]
if g.notna().any(axis=1).sum() < 2:
return np.nan
return np.nanstd(g, ddof=1)
df["std"] = df.reset_index().rolling(3)["day"].apply(fn).values
print(df)
Распечатки:
a b c std
day
1 NaN NaN NaN NaN
2 1.0 2.0 2.0 NaN
3 7.0 2.0 NaN 2.387467
4 2.0 9.0 7.0 3.116775
5 4.0 6.0 4.0 2.531939
Спасибо. Какова функция «(1,2)» в функции nanstd?