编写自定义 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 版本。