df_example = pd.DataFrame({'name': ['a', 'a', 'a', 'b', 'b', 'b'],
'class': [1, 2, 2, 3, 2, 2],
'price': [3, 4, 2, 1, 6, 5]})
Я хочу отфильтровать каждый name
, где price
больше наименьшего price
в подмножестве class==2
внутри name
группы:
df_example.sort_values(['name', 'price'], inplace=True)
df_tem = df_example[df_example['class'] == 2].groupby('name').first()
Ниже приведен псевдокод:
df_example.groupby('name').apply(lambda key, val: val['price'] > df_tem.loc[key]['price']).reset_index()
Есть ли какой-нибудь эффективный способ добиться чего-то вроде фильтра фрейма данных на основе подмножества внутри groupby
результат:
наименьшая цена с class=2
для каждой группы имен df_tem
:
class price
name
a 2 2
b 2 5
Поэтому,
group a: price>2; group b: price>5
выход:
pd.DataFrame({'name': ['a', 'a', 'b'],
'class': [1, 2, 2],
'price': [3, 4, 6]})
Обновлять:
на самом деле у меня есть идея создать новый столбец с именем «самый маленький», а затем отфильтровать
df_example by df_example['price'] > df_example['smallest '].
Знаете ли вы, как быстро создать такой столбец, что-то вроде
df_example['smallest '] = df_example[df_example['class'] == 2].groupby('name')['price'].transform('first')
вышеописанный способ еще есть nan
🤔 А знаете ли вы, что...
Python - это универсальный язык программирования.
Вы можете сделать это, используя groupby.transform, чтобы выровнять значение min
для каждого имени where
class==2 и сравнить gt
(больше чем) с ценой строки
df_output = (
df_example
.loc[lambda x:
x['price'].gt(x['price'].where(x['class'].eq(2))
.groupby(x['name']).transform(min))]
)
print(df_output)
# name class price
# 0 a 1 3
# 1 a 2 4
# 4 b 2 6
Вы можете получить min
цену для класса 2, merge
вставить ее df_example
в новый столбец min_price
, а затем использовать ее для фильтрации:
m = (
df_example[df_example["class"] == 2]
.groupby("name")["price"]
.min()
.reset_index(name = "min_price")
)
df_example = (
df_example.merge(m, how = "left", on = "name")
.query("price > min_price")
.drop(columns = "min_price")
)
name class price
0 a 1 3
1 a 2 4
4 b 2 6
Код
Используйте groupby
, чтобы агрегировать минимум, и используйте map
, чтобы сопоставить результат с name column
для логического индексирования.
m = df_example[df_example['class'] == 2].groupby('name')['price'].min()
out = df_example[df_example['price'] > df_example['name'].map(m)]
вне
name class price
0 a 1 3
1 a 2 4
4 b 2 6
обновить дополнительный вопрос
Кроме того, если вы хотите указать имя, для которого class=2
не существует, используйте код ниже.
m = df_example[df_example['class'] == 2].groupby('name')['price'].min()
cond1 = df_example['price'] > df_example['name'].map(m)
cond2 = ~df_example['name'].isin(m.index)
out = df_example[cond1 | cond2]
новый пример
df_example = pd.DataFrame({'name': ['a', 'a', 'a', 'b', 'b', 'b', 'c'],
'class': [1, 2, 2, 3, 2, 2, 3],
'price': [3, 4, 2, 1, 6, 5, 5]})
вне:
name class price
0 a 1 3
1 a 2 4
4 b 2 6
6 c 3 5