У меня есть датафрейм с записями, характеризующими поверхности крыш зданий, поэтому у каждого здания есть несколько плоскостей, с областью и описанием ее формы. например
df=pd.DataFrame([[1000, 12, 'slope'],
[1000, 10, 'flat'],
[1001, 10, 'slope'],
[1001, 15, 'flat'],
[1001, 7, 'slope']],
index = [1,2,3,4,5],
columns=['building_id', 'area', 'form'],
)
df
building_id area form
1 1000 12 slope
2 1000 10 flat
3 1001 10 slope
4 1001 15 flat
5 1001 7 slope
Я хочу объединить ряды, чтобы у меня было по одному для каждого здания, с общей площадью крыши и преобладающей формой крыши - то есть формой, которая имеет наибольшую площадь для этого здания, а не формой, которая появляется чаще всего:
df_out
building_id area form
1 1000 22 slope
2 1001 32 slope
Мне нужно что-то вроде этого:
group_functions={'area' : ['sum'],
'form' : lambda x: find_predominant(x)}
df_out = df.groupby('building_id').agg(group_functions)
Но find_predominant
должен быть функцией area
так же, как и form
: он возвращает строку 'flat'
или 'slope'
в зависимости от того, какая из них имеет наибольшую площадь для этого { { X5 } } .
Что такое функция find_predominant
? Или какой сценарий будет иметь такой же эффект?
2 ответа
Вы можете использовать sort_values
и назначить значение после agg
(df.groupby(['building_id','form'])['area']
.sum()
.sort_values()
.reset_index(level=1)
.groupby(level=0)
.agg({'form':'last','area':'sum'}))
form area
building_id
1000 slope 22
1001 slope 32
Я бы посоветовал рассчитать сумму и вызвать функцию find_predomonant
отдельно, поскольку для этого потребуется вызов apply
.
g = df.groupby('building_id')
area = g['area'].sum()
form = g.apply(find_predominant)
df_out = pd.concat([area, form], axis=1)
Теперь, чтобы это сработало, обратите внимание, что find_predominant
должен принять DataFrame и получить доступ к столбцам "area" и "form" соответствующим образом.
def find_predominant(df):
ar = df['area']
fm = df['form']
... # Do something with ar and fm
return result
Это может или не может потребовать рефакторинга с вашей стороны.
Редактировать: Хорошо, так что вы не знаете, что это за функция. В таком случае, давайте избавимся от этого.
Попробуй это.
area = df.groupby('building_id')['area'].sum()
form = (df.groupby(['building_id', 'form'])['area']
.sum()
.groupby(level=0)
.idxmax()
.str[1])
form.name = 'form'
df_out = pd.concat([area, form], axis=1).reset_index()
print(df_out)
building_id area form
0 1000 22 slope
1 1001 32 slope
Это выберет форму, соответствующую той, которая содержит максимальную площадь (по сумме) на building_id.
Если форма по максимальной сумме не требуется, и вы просто хотите форму по максимальной площади, тогда решение упрощается.
g = df.groupby('building_id')['area']
area = g.sum()
form = (df.set_index('building_id')
.iloc[g.idxmax(), df.columns.get_loc('form') - 1])
df_out = pd.concat([area, form], axis=1).reset_index()
print(df_out)
building_id area form
0 1000 22 flat
1 1001 32 slope
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.