Pandas 根据其他输出将 casts None dtype 应用于对象或浮点

Pandas apply casts None dtype to object or float depending on other outputs

提问人:Frank_Coumans 提问时间:10/16/2023 最后编辑:Frank_Coumans 更新时间:10/17/2023 访问量:43

问:

我想控制在一行上应用的输出 dtypes。下面的 foobar 有多个输出。

import pandas as pd

def foo(x):
    return x['a'] * x['b'], None, x['a'] > x['b']

def bar(x):
    return x['a'] * x['b'], None

df = pd.DataFrame([{'a': 10, 'b': 2}, {'a': 10, 'b': 20}])
df2 = df.copy()
df[['product', 'dummy', 'greater']] = df.apply(foo, axis=1, result_type='expand')
df2[['product', 'dummy']] = df2.apply(bar, axis=1, result_type='expand')

输出 dtypes 为:

山坳 DF系列 DF2型
一个 int64的 int64的
b int64的 int64的
产品 int64的 浮点64
虚拟 对象 浮点64
布尔值 -

对这个问题的评论 pandas apply changing dtype,建议 apply 返回具有单个 dtype 的系列。bar 可能就是这种情况,因为输出可以转换为浮点。但 foo 似乎并非如此,因为那样的话,输出就需要是 object。

是否可以控制 apply 的输出类型?即获取/指定 bar 的输出 dtypes (int, object),还是我需要在末尾强制转换 dtype?

背景: 我有一个数据帧,其中虚拟列的值为 True、False 和 None,并且 dtype 'object'。apply 函数在某些极端情况下运行,并引入了 NaN 而不是 None。我在应用后将 NaN 替换为 None,但它似乎过于复杂。

Pandas 版本 1.5.2

python pandas 数据帧 应用 dtype

评论


答:

1赞 Timeless 10/16/2023 #1

IIUC,你在问为什么在应用后有不同的 dtypes,即使这些函数返回的值对于这些新列是相同的?productdummyfoobar

       col      df      df2
0        a   int64    int64
1        b   int64    int64
2  product   int64  float64  # int64  <> float64
3    dummy  object  float64  # object <> float64
4  greater    bool         

如果是这样,那是因为当 时,在幕后用 infer_to_same_shape 做了一个特定的转换,大致相当于这样:result_type == "expand"

_datafoo = {0: (20, None, True), 1: (200, None, False)}
_databar = {0: (20, None), 1: (200, None)}

expandfoo = pd.DataFrame(_datafoo).T.set_axis(df.index).infer_objects()
expandbar = pd.DataFrame(_databar).T.set_axis(df.index).infer_objects()

输出 (foo) :

print(expandfoo.T, expandfoo, expandfoo.dtypes.to_dict(), sep="\n"*2)

      0      1
0    20    200
1  None   None
2  True  False

     0     1      2
0   20  None   True
1  200  None  False

{0: dtype('int64'), 1: dtype('O'), 2: dtype('bool')}

输出 (bar) :

print(expandbar.T, expandbar, expandbar.dtypes.to_dict(), sep="\n"*2)

      A      B
0  20.0  200.0
1   NaN    NaN  # <-- see the presence of NaN

       0   1
0   20.0 NaN
1  200.0 NaN

{0: dtype('float64'), 1: dtype('float64')}

正如你所看到的,infer_objects对两列都保持推断(如果这不直观,请参阅GH28318)。expandbarfloat64


是否可以控制 apply 的输出类型?

这取决于应用的函数所做的计算和返回的值。所以是的,你以某种方式拥有这种控制,但你总是可以在最后添加 convert_dtypesastype

评论

0赞 Frank_Coumans 10/17/2023
谢谢,这就是我想知道的。这是否意味着默认情况下应用输出是 dtype 对象
1赞 Timeless 10/17/2023
没有。例如,展开会导致列强制转换为 。因此,这取决于您的数据和应用的计算。fooproduct"int64"
0赞 Timeless 10/17/2023
我看到你更新了你的帖子。请注意 XY 问题
0赞 Frank_Coumans 10/17/2023
我试图让这个问题尽可能简单。但是,如果我再次有问题,我会提供一些背景信息。再次感谢您的解释。