Подтвердить что ты не робот

Как применять "первые" и "последние" функции к столбцам при использовании группы в pandas?

У меня есть кадр данных, и я хотел бы сгруппировать его по определенному столбцу (или, другими словами, по значениям из определенного столбца). Я могу сделать это следующим образом: grouped = df.groupby(['ColumnName']).

Я представляю результат этой операции как таблицы, в которой некоторые ячейки могут содержать наборы значений вместо одиночных значений. Чтобы получить обычную таблицу (т.е. Таблицу, в которой каждая ячейка содержит только одно единственное значение), мне нужно указать, какую функцию я хочу использовать для преобразования наборов значений в ячейках в отдельные значения.

Например, я могу заменить наборы значений по их сумме или по их минимальному или максимальному значению. Я могу сделать это следующим образом: grouped.sum() или grouped.min() и т.д.

Теперь я хочу использовать разные функции для разных столбцов. Я понял, что могу сделать это следующим образом: grouped.agg({'ColumnName1':sum, 'ColumnName2':min}).

Однако по некоторым причинам я не могу использовать first. Более подробно, grouped.first() работает, но grouped.agg({'ColumnName1':first, 'ColumnName2':first}) не работает. В результате я получаю NameError: NameError: name 'first' is not defined. Итак, мой вопрос: почему это происходит и как решить эту проблему.

ADDED

Здесь я нашел следующий пример:

grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean})

Может быть, мне также нужно использовать np? Но в моем случае python не распознает "np". Должен ли я импортировать его?

4b9b3361

Ответ 1

Я думаю, что проблема в том, что существуют два разных метода first, которые используют имя, но действуют по-разному: для groupby objects и другой для серии /DataFrame (в зависимости от времени).

Чтобы воспроизвести поведение метода groupby first над DataFrame с помощью agg, вы можете использовать iloc[0] (который получает первую строку в каждой группе (DataFrame/Series) по индексу):

grouped.agg(lambda x: x.iloc[0])

Например:

In [1]: df = pd.DataFrame([[1, 2], [3, 4]])

In [2]: g = df.groupby(0)

In [3]: g.first()
Out[3]: 
   1
0   
1  2
3  4

In [4]: g.agg(lambda x: x.iloc[0])
Out[4]: 
   1
0   
1  2
3  4

Аналогично, вы можете реплицировать last с помощью iloc[-1].

Примечание. Это будет работать со столбцами и другими:

g.agg({1: lambda x: x.iloc[0]})

В старой версии pandas вы могли бы использовать метод irow (например, x.irow(0), см. предыдущие изменения.


Несколько обновленных заметок:

Это лучше сделать с помощью метода nth, который намного быстрее >= 0,13:

g.nth(0)  # first
g.nth(-1)  # last

Вам нужно немного позаботиться, поскольку поведение по умолчанию для first и last игнорирует строки NaN... и IIRC для DataFrame groupbys было прервано до 0.13... там есть опция dropna для nth.

Вы можете использовать строки, а не встроенные (хотя IIRC pandas указывает на встроенный sum и применяет np.sum):

grouped['D'].agg({'result1' : "sum", 'result2' : "mean"})

Ответ 2

Вместо использования first или last используйте их строковые представления в методе agg. Например, в случае OP:

grouped = df.groupby(['ColumnName'])
grouped['D'].agg({'result1' : np.sum, 'result2' : np.mean})

#you can do the string representation for first and last
grouped['D'].agg({'result1' : 'first', 'result2' : 'last'})

Ответ 3

Я не уверен, действительно ли это проблема, но sum и min - это встроенные модули Python, которые принимают некоторые итерации в качестве входных данных, тогда как first - это метод объекта pandas Series, поэтому возможно, это не в вашем пространстве имен. Кроме того, в качестве ввода требуется что-то другое (документ указывает некоторое значение смещения).

Я предполагаю, что один из способов обойти это - создать свою собственную функцию first и определить ее так, чтобы в качестве ввода использовался объект Series, например:

def first(Series, offset):
    return Series.first(offset)

или что-то в этом роде.