У меня есть такой фрейм данных
дф
Node_Name size count
Abc1 10 2
Abc1 20 2
Zxd 30 3
Zxd 40 3
Zxd 80 3
Ddd 10 4
Ddd 40 4
Ddd 80 4
Ddd 100 4
Мне нужно подмножество этого кадра данных как это.
Если значение счетчика для каждого Node_Name равно 2 или меньше, возьмите минимальное значение для каждого Node_Name. Если счетчик равен 3 или более, удалите максимальное значение и добавьте размер значений, кроме группы максимальных значений tge, по Node_Name.
Например, Final_df должен выглядеть так:
Node_Name size count
Abc1 10 2
Zxd 70 3
Ddd 130 4
В чем именно вам нужна помощь? Что вам мешает сделать это самому? Для начала, вы знаете, как использовать groupby?
Если я хорошо понимаю логику, для каждой группы с groupby.apply возьмите 2 наименьших значения и просуммируйте, если количество > 2, иначе мин:
out = (df.groupby(['Node_Name', 'count'], sort=False)['size']
.apply(lambda x: x.nsmallest(2).sum() if x.name[1] > 2 else x.min())
.reset_index()
)
Примечание. x.name
содержит идентификатор группы (для первой это ('Abc1', 2)
), поэтому x.name[1]
— это счетчик.
Выход:
Node_Name count size
0 Abc1 2 10
1 Zxd 3 70
2 Ddd 4 50
out = (df.groupby(['Node_Name', 'count'], sort=False)['size']
.agg(lambda x: x.sort_values().iloc[:-1].sum())
)
# or
out = (df.groupby(['Node_Name', 'count'], sort=False)['size']
.agg(lambda x: x.nsmallest(len(x)-1).sum())
)
Выход:
Node_Name count size
0 Abc1 2 10
1 Zxd 3 70
2 Ddd 4 130
иногда число может превышать 3. Если оно больше или равно 3, просуммируйте размер меньшего 2.
Не совсем: здесь просто бывает, что Abc1
имеет только две записи, но в ОП указано, что если count <= 2, то минимальное значение должно быть взято, даже если записей больше двух.
@mozway, для Abc1, выходное значение должно быть 10, а не 30
Упс, действительно, я это исправлю чуть позже, увлекся чем-то в реале
@NickD, все исправлено, спасибо, что сообщили мне!
@mozway, извини, мне пришлось обновить вопрос. Если количество нас больше 2, удалите значение максимального размера и добавьте остальные. Если размер равен 2, возьмите минимальное значение размера.
@user1471980 user1471980, если вы поняли логику, это практически то же самое, см. Редактировать
@mozway, если количество 4, мне нужно добавить меньшие 3 значения, если пять, добавить меньшие значения c4, в основном удалить максимальное значение и добавить группу других значений по Node_Name
Хорошо, тогда я думаю groupby.agg
немного похоже на мой первоначальный подход, посмотрите
df = df.sort_values(['Node_Name', 'size']).reset_index(drop = True)
first = df['Node_Name'].shift(1) != df['Node_Name']
first_two = df['Node_Name'].shift(2) != df['Node_Name']
more_than_two = df['count'] > 2
df2 = df[first | (first_two & more_than_two)].groupby('Node_Name')['size'].sum()
Альтернативный метод фильтрации строк с использованием группировок:
from functools import reduce
rows = []
for ind in df.groupby('Node_Name').groups.values():
if len(ind) > 2:
rows.append(ind[0:2])
else:
rows.append(ind[0:1])
df.loc[reduce(lambda a, b: a.append(b), rows)].groupby('Node_Name')['size'].sum()
Связано ли значение счетчика с размером группы, если она сгруппирована по имени узла?