Pandas:apply result_type="expand":错误的数据类型。

4

我想向DataFrame中添加多列:

import pandas as pd

df = pd.DataFrame(
    [
        (0, 1),
        (1, 1),
        (1, 2),
    ],
    columns=['a', 'b']
)


def apply_fn(row) -> (int, float):
    return int(row.a + row.b), float(row.a / row.b)


df[['c', 'd']] = df.apply(apply_fn, result_type='expand', axis=1)

结果:

>>> df
   a  b    c    d
0  0  1  1.0  0.0
1  1  1  2.0  1.0
2  1  2  3.0  0.5

>>> df.dtypes
a      int64
b      int64
c    float64
d    float64
dtype: object

为什么列c的数据类型不是int?有没有办法指定它为int类型?例如像.apply(..., dtypes=[int, float])这样的方式。

你使用apply的原因是什么?为什么不使用向量化选项? - sammywemmy
你的意思是为什么不用 df['c'] = df['a'] + df['b'] 呢?是的,有一个很好的理由。这只是一个玩具示例。 - MrTomRod
2个回答

4

我认为这是由于 result_type='expand' 的原因导致被展开成为一个Series,因此第一 是在它自己的Series中,然后是下一行,以此类推。但是,由于Series对象只能有一个dtype,所以整数会被转换为浮点数。

例如,看看这个:

>>> pd.Series([1, 0.0])
0    1.0
1    0.0
dtype: float64

一种解决方法是在apply调用上调用tolist,然后将其包装在对DataFrame的调用中:

>>> df[['c', 'd']] = pd.DataFrame(df.apply(apply_fn, axis=1).tolist())
   a  b  c    d
0  0  1  1  0.0
1  1  1  2  1.0
2  1  2  3  0.5

谢谢您的快速回复!我猜性能并不是很好,是吗?我需要在一个大的数据框上快速应用。 - MrTomRod
2
我不是很确定。我会假设性能接近于您的原始代码,但由于使用了“apply”,可能会变慢... - user17242583
是的,我想最终会使用numpy和Cython... - MrTomRod

2
您可以使用 astype 进行链式操作。
df.apply(apply_fn, axis=1, result_type='expand').astype({0:'int', 1:'float'})
Out[147]: 
   0    1
0  1  0.0
1  2  1.0
2  3  0.5

谢谢!但是这个方法比.tolist()慢了2倍。 - MrTomRod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接