У меня есть фрейм данных, который выглядит так:
pd.DataFrame({'A': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'],
...: 'rank': [1, 2, 3, 4, 5, 6, 7, 8],
...: 'value': [8, 6, np.nan, 7, 9, np.nan, 4, np.nan]})
Out[4]:
A rank value
0 A 1 8.0
1 B 2 6.0
2 C 3 NaN
3 D 4 7.0
4 E 5 9.0
5 F 6 NaN
6 G 7 4.0
7 H 8 NaN
Для всех значений NaN я хотел бы назначить минимальное значение группы элементов, которые ранжируются выше своего собственного ранга.
Логика:
C имеет ранг 3, 2 элемента, ранжированные выше (A и B), имеют минимальное значение 6, поэтому C должно быть присвоено значение 6.
F имеет ранг 6, элементы, ранжированные выше (A, B, C, D, E), имеют минимальное значение 6, поэтому C должно быть присвоено значение 6
H имеет ранг 8, элементы, ранжированные выше (A, B, C, D, E, F, G), имеют минимальное значение 4, поэтому H следует присвоить значение 4
результирующий фрейм данных должен выглядеть так
A rank value
0 A 1 8.0
1 B 2 6.0
2 C 3 6.0
3 D 4 7.0
4 E 5 9.0
5 F 6 6.0
6 G 7 4.0
7 H 8 4.0
Как этого добиться с помощью 1 или 2 строк кода?
adf = df[df['value'].isnull()]
for i, r in adf.iterrows():
df.loc[i, 'value'] = df[df['rank'] < r['rank']]['value'].values.min()
Если у вас есть повторяющиеся ранги, некоторые из которых являются NaN, то:
adf = df[df['value'].isnull()]
bdf = df[~df['value'].isnull()]
for i, r in adf.iterrows():
df.loc[i, 'value'] = bdf[bdf['rank'] < r['rank']]['value'].values.min()
Вычислите кумулятивный минимум для всех строк. Заполните Na
на fillna
df['mincum'] = df['value'].expanding().min()
df['value'] = df['value'].fillna(df['mincum'])
df
Использование Series.cummin
df['mincum'] = df['value'].cummin(skipna=True).ffill()
df['value'] = df['value'].fillna(df['mincum'])
Однострочные без использования дополнительных вспомогательных столбцов.
expanding.mean
:
df['value'] = df['value'].fillna(df['value'].expanding().min())
Series.cummin
df['value'] = df['value'].fillna(df['value'].cummin(skipna=True).ffill())
Еще одна попытка:
idx = df.loc[df['value'].isnull(),'value'].index
for i in idx:
df.loc[i,'value'] = df.loc[:i-1,'value'].min()
Отпечатки:
A rank value
0 A 1 8.0
1 B 2 6.0
2 C 3 6.0
3 D 4 7.0
4 E 5 9.0
5 F 6 6.0
6 G 7 4.0
7 H 8 4.0