如何将 round 应用于两个 pandas 列

3
我正在尝试将 pandas 数据帧中一列的值四舍五入到另一列指定的小数位数,如下所示的代码。
    df = pandas.DataFrame({
        'price': [14.5732, 145.731, 145.722, 145.021],
        'decimal': [4, 3, 2, 2]
    })
    df['price'] = df.apply(lambda x: round(x.price, x.decimal), axis=1)

然而,这样做会导致以下错误:
>   df['price'] = df.apply(lambda x: round(x.price, x.decimal), axis=1)
E   TypeError: ('integer argument expected, got float', 'occurred at index 0')

文档让人觉得round期望在索引0处接收一个浮点数,但显然它不满意。将价格更改为整数可以解决错误,但这会破坏代码本身的意义。


2
[round(x, y) for x, y in zip(df['price'], df['decimal'])]。这种做法应该比使用 apply 更快。 - user3483203
1
你的尝试失败的原因是 decimal 被强制转换为浮点数。如果你想验证这一点,请尝试使用 df.apply(lambda x: x, axis=1) - user3483203
我处理非常大的数据集,因此内存使用比速度更重要。zip会创建一个大的中间对象吗? - Jonathan Vehaun
1
不,它是惰性求值的。 - user3483203
尝试在apply中使用round(x.price, int(x.decimal)) - Shubham Shaswat
3个回答

0

这是Pandas中一个长久以来的痛点。当访问单个行或在第一轴上调用apply时,dtype强制转换经常发生。错误消息很令人困惑,因为您的十进制系列的dtype明显是整数类型,所以应该被round方法接受,但是强制转换是在幕后发生的。

您可以使用ilocapply进行检查:

>>> df.iloc[0]
price      14.5732
decimal     4.0000
Name: 0, dtype: float64

>>> df.apply(lambda x: x, axis=1)
      price  decimal
0   14.5732      4.0
1  145.7310      3.0
2  145.7220      2.0
3  145.0210      2.0

更令人沮丧的是,如果您有一个对象数据类型列,那么没有任何强制转换,因此行为并不容易预测!
>>> df['foo'] = 'bar'
>>> df.iloc[0]
price      14.5732
decimal          4
foo            bar
Name: 0, dtype: object

长话短说,这很混乱,一点也不直观。有几个解决方法,可以在 lambda 函数中转换小数或使用列表推导式(可能比 apply 更快)。
>>> df.apply(lambda x: round(x.price, int(x.decimal)), axis=1)
0     14.5732
1    145.7310
2    145.7200
3    145.0200
dtype: float64

>>> [round(x, y) for x, y in zip(df['price'], df['decimal'])]
[14.5732, 145.731, 145.72, 145.02]

请注意,当以系列形式显示时,表示不会改变,但值将已被四舍五入。

0

你可以这样使用生成器:

>>> gen = (i for i in df.decimal)
>>> df.price = df.price.apply(lambda x: round(x, next(gen))) 
>>> df
      price  decimal
0   14.5732        4
1  145.7310        3
2  145.7200        2
3  145.0200        2

为什么不使用 [ ] 来访问列? - AMC
@AMC 不想再按更多的键了 - Vicrobot

0

它有效:

df['price'] = df.apply(lambda x: round(x.price, int(x.decimal)), axis=1)

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