python #pandas
#python #pandas #агрегировать
Вопрос:
Я часто использовал agg()
функцию pandas для запуска сводной статистики по каждому столбцу data.frame. Например, вот как вы могли бы получить среднее и стандартное отклонение:
df = pd.DataFrame({'A': ['group1', 'group1', 'group2', 'group2', 'group3', 'group3'],
'B': [10, 12, 10, 25, 10, 12],
'C': [100, 102, 100, 250, 100, 102]})
>>> df
[output]
A B C
0 group1 10 100
1 group1 12 102
2 group2 10 100
3 group2 25 250
4 group3 10 100
5 group3 12 102
В обоих этих случаях порядок отправки отдельных строк в функцию agg не имеет значения. Но рассмотрим следующий пример, который:
df.groupby('A').agg([np.mean, lambda x: x.iloc[1] ])
[output]
mean <lambda> mean <lambda>
A
group1 11.0 12 101 102
group2 17.5 25 175 250
group3 11.0 12 101 102
В этом случае лямбда-выражение функционирует по назначению, выводя вторую строку в каждой группе. Однако я не смог найти ничего в документации pandas, что подразумевает, что это гарантированно будет верно во всех случаях. Я хочу использовать agg()
вместе с функцией средневзвешенного значения, поэтому я хочу быть уверенным, что строки, входящие в функцию, будут в том же порядке, в каком они отображаются в исходном фрейме данных.
Кто-нибудь знает, в идеале, где-нибудь в документации или исходном коде pandas, если это гарантированно так?
Комментарии:
1. Да, я не вижу никаких гарантий, что порядок сохраняется в документах, поэтому полагаться на него немного неразумно. Если порядок отражается в вашем
B
столбце, вы можете отсортировать каждую группуB
по лямбде, чтобы убедиться.2. К сожалению, я хочу сохранить строки, упорядоченные по столбцу, который не включен в агрегацию. Фрейм данных сортируется перед
agg()
вызовом, поэтому проблема возникает только в том случае, если он переупорядочивает его как частьgroupby()
.
Ответ №1:
См. Эту проблему с улучшением
Короткий ответ — да, groupby сохранит порядок, переданный. Вы можете доказать это, используя свой пример следующим образом:
In [20]: df.sort_index(ascending=False).groupby('A').agg([np.mean, lambda x: x.iloc[1] ])
Out[20]:
B C
mean <lambda> mean <lambda>
A
group1 11.0 10 101 100
group2 17.5 10 175 100
group3 11.0 10 101 100
Однако это НЕВЕРНО для повторной выборки, поскольку для этого требуется монотонный индекс (он БУДЕТ работать с немонотонным индексом, но сначала отсортирует его).
Это sort=
флаг для groupby, но это относится к сортировке самих групп, а не к наблюдениям внутри группы.
К вашему сведению: df.groupby('A').nth(1)
это безопасный способ получить 2-е значение группы (поскольку ваш метод, описанный выше, завершится неудачей, если в группе <2 элементов)
Комментарии:
1. Спасибо за разъяснения и ссылку на проблему! Первоначально я использовал
iloc
в качестве примера, потому что не мог понять, как перейтиnth()
кagg()
вызову (потому что в этот моментx
это серия). Есть ли какой-либо способ вызоваnth()
, отличный от функции-члена DataFrame?2.
nth
определяется только для groupby. Что вы имеете в виду «кроме функции-члена DataFrame»?3. Я имел в виду, что не мог понять, как передать
nth()
в качестве одной из функций, отправленных в спискеagg()
. Вы не можете сделать.agg([np.mean, nth])
, илиDataFrame.nth()
илиlambda x: x.nth(2)
. Это то, что привело меня к iloc, хотя это приведет к ошибкам индекса. Вероятно, лучший способ — не пытаться сделать все это за один шаг; сначала используйтеnth()
, затем используйтеagg()
, затем объедините их.
Ответ №2:
В документе Panda 0.19.1 говорится, что «groupby сохраняет порядок строк в каждой группе», так что это гарантированное поведение.
http://pandas.pydata.org/pandas-docs/stable/generated/pandas .DataFrame.groupby.html
Ответ №3:
Чтобы сохранить порядок, вам нужно пройти .groupby(..., sort=False)
. В вашем случае столбец группировки уже отсортирован, поэтому это не имеет значения, но обычно необходимо использовать sort=False
флаг:
df.groupby('A', sort=False).agg([np.mean, lambda x: x.iloc[1] ])
Комментарии:
1. Для groupby есть флаг sort= , но это относится к сортировке самих групп, а не к наблюдениям внутри группы.
2. они должны были сделать это параметром по умолчанию, учитывая, что очень часто это используется
3. По иронии судьбы, в документации также говорится: «Повысьте производительность, отключив это». Ну, еще одна причина, по которой это должно было быть необязательной функцией, а не функцией по умолчанию. Самое главное, что он вносит изменения в данные, которых вызывающий абонент может и не ожидать.
Ответ №4:
Ссылка: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas .DataFrame.groupby.html
API принимает «СОРТИРОВКУ» в качестве аргумента.
Описание для аргумента СОРТИРОВКИ выглядит следующим образом:
сортировка: bool, по умолчанию Истинные ключи группы сортировки. Повысьте производительность, отключив эту функцию. Обратите внимание, что это не влияет на порядок наблюдений внутри каждой группы. Groupby сохраняет порядок строк внутри каждой группы.
Таким образом, ясно, что «Groupby» сохраняет порядок строк внутри каждой группы.
Ответ №5:
К сожалению, ответ на этот вопрос ОТРИЦАТЕЛЬНЫЙ. За последние несколько дней я создал алгоритм для неравномерного разбиения на фрагменты и обнаружил, что он не может сохранить порядок, потому что groupby вводит подкадры, где ключом к каждому кадру является ввод groupby. Итак, вы получаете:
allSubFrames = df.groupby("myColumnToOrderBy")
for orderKey, individualSubFrame in allSubFrames:
do something...
Поскольку он использует словари, вы теряете порядок.
Если после этого вы выполните сортировку, как упоминалось выше, которую я только что протестировал для большого набора данных, вы получите вычисление O (n log n) .
Однако я обнаружил, что если у вас, например, упорядочены данные временных рядов по порядку, где вы хотите сохранить порядок, лучше изменить столбец упорядочения в список, а затем создать счетчик, который записывает первый элемент в каждом временном ряду. Это приводит к вычислению O (n) .
Итак, по сути, если вы используете относительно небольшой набор данных, предложенные выше ответы являются разумными, но при использовании большого набора данных вам необходимо рассмотреть возможность отказа от groupby и сортировки. Вместо этого используйте: list(df['myColumnToOrderBy'])
и итератор над ним.
Комментарии:
1. Не могли бы вы, пожалуйста, добавить простой пример рабочего кода к своему ответу?
2. Нет, я не могу, потому что вам нужен огромный набор данных, и мне потребовалось много времени, чтобы разобраться с этой проблемой, и я больше не работаю над этим проектом.
Ответ №6:
Еще проще:
import pandas as pd
pd.pivot_table(df,index='A',aggfunc=(np.mean))
вывод:
B C
A
group1 11.0 101
group2 17.5 175
group3 11.0 101