我有一个数据框,其中记录了建筑物屋顶表面的特征,因此每座建筑物都有多个平面,并带有面积和形式描述。例如
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'
,具体取决于哪个字符串最大building_id
的区域。
函数find_predominant
是什么?还是什么脚本会产生相同的效果?
答案 0 :(得分:3)
我的建议是计算总和并分别调用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并适当地访问“区域”和“表单”列。
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
答案 1 :(得分: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