编写自定义 pandas aggfunc 而不使所有 dtypes 对象
Writing custom pandas aggfunc without making all dtypes object
我(认为我)需要为 geopandas.GeoDataFrame.dissolve() 操作编写自定义聚合函数。合并多个多边形时,我想保留面积最大的多边形的信息,同时满足其他条件。该操作工作正常,但之后我的 GeoDataFrame 的所有属性都是 dtype object
.
常规 pandas groupy()
也会出现同样的问题,因此我简化了下面的示例。有人可以告诉我是否应该以不同的方式编写我的 custom_sort()
以保持数据类型完整吗?
import pandas as pd
df = pd.DataFrame({
'group': ['A', 'A', 'B', 'B'],
'ints': [1, 2, 3, 4],
'floats': [1.0, 2.0, 2.2, 3.2],
'strings': ['foo', 'bar', 'baz', 'qux'],
'bools': [True, True, True, False],
'test': ['drop this', 'keep this', 'keep this', 'drop this'],
})
def custom_sort(df):
"""Define custom aggregation function with special sorting."""
df = df.sort_values(by=['bools', 'floats'], ascending=False)
return df.iloc[0]
print(df)
print(df.dtypes)
print()
grouped = df.groupby(by='group').agg(custom_sort)
print(grouped)
print(grouped.dtypes) # Issue: All dtypes are object
print()
print(grouped.convert_dtypes().dtypes) # Possible solution, but not for me
# Please note that I cannot use convert_dtypes(). I actually need this for
# geopandas.GeoDataFrame.dissolve() and I think convert_dtypes() messes up
# the geometry information
输出:
group ints floats strings bools test
0 A 1 1.0 foo True drop this
1 A 2 2.0 bar True keep this
2 B 3 2.2 baz True keep this
3 B 4 3.2 qux False drop this
group object
ints int64
floats float64
strings object
bools bool
test object
dtype: object
ints floats strings bools test
group
A 2 2.0 bar True keep this
B 3 2.2 baz True keep this
ints object
floats object
strings object
bools object
test object
dtype: object
ints Int64
floats Float64
strings string
bools boolean
test string
dtype: object
问题的根源是df.iloc[0]
returns一个pandas系列。该系列中有多个值,具有不同的数据类型。 pandas 可能会自动将系列的 dtype 转换为 object
。 如果我没记错的话,这取决于您使用的 pandas 库的版本 。随着时间的推移,此行为已发生变化。
您的问题的解决方案在很大程度上取决于您在自定义 agg
函数中执行的操作。
在您的玩具示例中,我建议您事先处理您的数据框,并使用可能的简单聚合函数。
例如,预测复杂的逻辑给出一个简单的 head
作为 agg:
(df.sort_values(by=['bools', 'floats'],
ascending=False)
.groupby(by='group')
.agg('first')
对于有价值的东西,我还建议您使用更新的 pandas
版本。
我(认为我)需要为 geopandas.GeoDataFrame.dissolve() 操作编写自定义聚合函数。合并多个多边形时,我想保留面积最大的多边形的信息,同时满足其他条件。该操作工作正常,但之后我的 GeoDataFrame 的所有属性都是 dtype object
.
常规 pandas groupy()
也会出现同样的问题,因此我简化了下面的示例。有人可以告诉我是否应该以不同的方式编写我的 custom_sort()
以保持数据类型完整吗?
import pandas as pd
df = pd.DataFrame({
'group': ['A', 'A', 'B', 'B'],
'ints': [1, 2, 3, 4],
'floats': [1.0, 2.0, 2.2, 3.2],
'strings': ['foo', 'bar', 'baz', 'qux'],
'bools': [True, True, True, False],
'test': ['drop this', 'keep this', 'keep this', 'drop this'],
})
def custom_sort(df):
"""Define custom aggregation function with special sorting."""
df = df.sort_values(by=['bools', 'floats'], ascending=False)
return df.iloc[0]
print(df)
print(df.dtypes)
print()
grouped = df.groupby(by='group').agg(custom_sort)
print(grouped)
print(grouped.dtypes) # Issue: All dtypes are object
print()
print(grouped.convert_dtypes().dtypes) # Possible solution, but not for me
# Please note that I cannot use convert_dtypes(). I actually need this for
# geopandas.GeoDataFrame.dissolve() and I think convert_dtypes() messes up
# the geometry information
输出:
group ints floats strings bools test
0 A 1 1.0 foo True drop this
1 A 2 2.0 bar True keep this
2 B 3 2.2 baz True keep this
3 B 4 3.2 qux False drop this
group object
ints int64
floats float64
strings object
bools bool
test object
dtype: object
ints floats strings bools test
group
A 2 2.0 bar True keep this
B 3 2.2 baz True keep this
ints object
floats object
strings object
bools object
test object
dtype: object
ints Int64
floats Float64
strings string
bools boolean
test string
dtype: object
问题的根源是df.iloc[0]
returns一个pandas系列。该系列中有多个值,具有不同的数据类型。 pandas 可能会自动将系列的 dtype 转换为 object
。 如果我没记错的话,这取决于您使用的 pandas 库的版本 。随着时间的推移,此行为已发生变化。
您的问题的解决方案在很大程度上取决于您在自定义 agg
函数中执行的操作。
在您的玩具示例中,我建议您事先处理您的数据框,并使用可能的简单聚合函数。
例如,预测复杂的逻辑给出一个简单的 head
作为 agg:
(df.sort_values(by=['bools', 'floats'],
ascending=False)
.groupby(by='group')
.agg('first')
对于有价值的东西,我还建议您使用更新的 pandas
版本。