Как я могу эффективно фильтровать и агрегировать данные в Pandas DataFrame с несколькими условиями?

У меня есть большой DataFrame Pandas с несколькими столбцами, включая категорию, подкатегорию, значение и дату. Мне нужно отфильтровать этот DataFrame на основе нескольких условий, а затем агрегировать отфильтрованные результаты. В частности, я хочу:

Filter rows where Category is either "A" or "B".
Further filter these rows to include only those where Value is greater than 10.
Group the filtered data by SubCategory and calculate the sum of Value for each SubCategory.
Sort the results by the summed Value in descending order.

Вот упрощенная версия моего DataFrame:

data = {
    'Category': ['A', 'B', 'A', 'C', 'B', 'A'],
    'SubCategory': ['X', 'Y', 'X', 'Z', 'X', 'Y'],
    'Value': [5, 15, 20, 25, 10, 30],
    'Date': pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05', '2023-01-06'])
}
df = pd.DataFrame(data)

Для достижения этой цели я попытался объединить несколько методов Pandas, но не уверен, что это наиболее эффективный способ сделать это. Вот мой текущий подход:

filtered_df = df[(df['Category'].isin(['A', 'B'])) & (df['Value'] > 10)]
grouped_df = filtered_df.groupby('SubCategory')['Value'].sum().reset_index()
sorted_df = grouped_df.sort_values(by='Value', ascending=False)
print(sorted_df)

Кажется, этот код работает, но меня беспокоит его эффективность и читаемость, особенно с гораздо большим набором данных.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
82
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

То, что у вас есть, хорошо: использование масок, как правило, является лучшим методом фильтрации, поскольку они очень эффективны даже для больших наборов данных.

Полагаю, можно было бы заранее выбрать нужные столбцы:

output = (
    df.loc[
        df.Category.isin(['A', 'B'])  # Filter rows where Category is either "A" or "B".
        & df.Value.gt(10),  # Further filter these rows to include only those where Value is greater than 10.
        ["SubCategory", "Value"],
    ]
    .groupby("SubCategory", as_index=False).sum()  # Group the filtered data by SubCategory and calculate the sum of Value for each SubCategory.
    .sort_values(by = "Value", ascending=False)  # Sort the results by the summed Value in descending order.
)

Такое форматирование также позволяет оставлять комментарии на каждом этапе~

Ответ принят как подходящий

Я предлагаю выполнить сравнение, если значение> 10 после фильтра данных для категорий (чтобы не проверять значение> 10 для каждого значения исходного кадра данных), например:

out = (
    df[df.Category.isin(["A", "B"])]
    .query("Value > 10")
    .groupby("SubCategory", as_index=False)["Value"]
    .sum()
    .sort_values(by = "Value", ascending=False)
)
print(out)

Распечатки:

  SubCategory  Value
1           Y     45
0           X     20

Другие вопросы по теме