首页 > 解决方案 > 将函数应用于 Pandas DataFrame 的列,以数据类型为条件

问题描述

我想使用通用模式将函数应用于 Pandas DataFrame 中的每一列,但该函数应该以列数据类型为条件。

听起来很简单。但是我在测试数据类型时发现了一个奇怪的行为,我在文档中找不到任何地方或在谷歌上搜索它的原因。

考虑这个代表:

import pandas as pd

toydf = pd.DataFrame(dict(
    A = [1, 2, 3],
    B = [1.1, 1.2, 1.3],
    C = ['1', '2', '3'],
    D = [True, True, False]
))

分别检查它们的 dtypesdtype('int64'), dtype('float64'), dtype('O'), dtype('bool')

但是,如果我使用该apply函数,则传递给该函数的所有列都是dtype: object.

def dtype_fn(the_col):
    print(the_col)
    return(the_col.dtype)

toydf.apply(dtype_fn)

toydf.apply(dtype_fn)
0    1
1    2
2    3
Name: A, dtype: object
0    1.1
1    1.2
2    1.3
Name: B, dtype: object
0    1
1    2
2    3
Name: C, dtype: object
0     True
1     True
2    False
Name: D, dtype: object
Out[167]: 
A    object
B    object
C    object
D    object
dtype: object

这是为什么?,我做错了什么?,为什么列不保留原始数据类型?

这是一种可行并产生我想要的输出的方法:(但出于封装原因,我不喜欢它)

def dtype_fn2(col_name):
    return(toydf[col_name].dtype)

[dtype_fn2(col) for col in toydf.columns]

Out[173]: [dtype('int64'), dtype('float64'), dtype('O'), dtype('bool')]

标签: pythonpandas

解决方案


这个评论是正确的。此行为是设计使然。对于给定的所有 dtype,Pandas “应用”类型层次结构中最高的类型。

考虑将函数仅应用于“A”,

df[['A']].apply(dtype_fn)
int64

A    int64
dtype: object

同样,只有“A”和“B”,

df[['A', 'B']].apply(dtype_fn)
float64
float64

A    float64
B    float64
dtype: object

由于您有多种类型,包括原始 DataFrame 中的字符串,所以它们的通用类型都是object.


现在这解释了这种行为,但我仍然需要解决这个问题。Pandas 提供了一种有用的方法:Series.infer_objects推断 dtype 并执行“软转换”。

如果确实需要函数中的类型,可以在调用dtype. 这会产生预期的结果:

def dtype_fn(the_col):
     the_col = the_col.infer_objects()
     print(the_col.dtype)

     return(the_col.dtype)

df.apply(dtype_fn)
int64
float64
object
bool

A      int64
B    float64
C     object
D       bool
dtype: object

推荐阅读