【问题标题】:Cubic Root of Pandas DataFramePandas DataFrame 的三次方根
【发布时间】:2017-11-10 08:09:45
【问题描述】:

我了解如何取正数和负数的立方根。但是当尝试使用apply-lambda 方法来有效地处理数据帧的所有元素时,我遇到了一个模棱两可的问题。有趣的是,等式不会出现这个错误,所以我想知道代码可能有什么问题:

sample[columns]=sample[columns].apply(lambda x: (-1)*np.power(-x,1./3) if x<0 else np.power(x,1./3))

【问题讨论】:

  • 您能否提供一个重现错误的工作示例?在一个样本上试了一下,效果很好。

标签: python python-3.x pandas numpy dataframe


【解决方案1】:

看起来您正在传递列名的列表或数组。我假设这是因为您的变量名称是复数,末尾带有 s。如果是这种情况,那么sample[columns] 是一个数据框。这是一个问题,因为apply 遍历每一列,将您传递给applylambda 传递给该列。所以你得到了

(-1) * np.power(-series_object, -1./3) if series_object < 0 else...

series_object &lt; 0 搞砸了,因为您要求整个系列的真实性小于零。


applymap

f = lambda x: -np.power(-x, 1./3) if x < 0 else np.power(x, 1./3)
sample[columns] = sample[columns].applymap(f)

也就是说,我会使用定义如下的lambda

f = lambda x: np.sign(x) * np.power(abs(x), 1./3)

然后您可以在整个数据帧上执行此操作

np.random.seed([3,1415])
df = pd.DataFrame(np.random.randint(-10, 10, (5, 5)))

df

    0  1   2  3   4
0   6  1  -8  0   5
1   3  1   3  9  -2
2 -10  2 -10 -8 -10
3  -3  9   3  8   2
4  -6 -7   9  3  -3

f = lambda x: np.sign(x) * np.power(abs(x), 1./3)
f(df)

          0         1         2         3         4
0  1.817121  1.000000 -2.000000  0.000000  1.709976
1  1.442250  1.000000  1.442250  2.080084 -1.259921
2 -2.154435  1.259921 -2.154435 -2.000000 -2.154435
3 -1.442250  2.080084  1.442250  2.000000  1.259921
4 -1.817121 -1.912931  2.080084  1.442250 -1.442250

df.applymap(f)

          0         1         2         3         4
0  1.817121  1.000000 -2.000000  0.000000  1.709976
1  1.442250  1.000000  1.442250  2.080084 -1.259921
2 -2.154435  1.259921 -2.154435 -2.000000 -2.154435
3 -1.442250  2.080084  1.442250  2.000000  1.259921
4 -1.817121 -1.912931  2.080084  1.442250 -1.442250

检查是否相等

df.applymap(f).equals(f(df))

True

而且速度更快

%timeit df.applymap(f)
%timeit f(df)

1000 loops, best of 3: 1.11 ms per loop
1000 loops, best of 3: 473 µs per loop

【讨论】:

    【解决方案2】:

    不必复杂,使用 NumPys 立方根函数即可:np.cbrt:

    df[columns] = np.cbrt(df[columns])
    

    它需要NumPy &gt;= 1.10


    对于旧版本,您可以使用 np.absolutenp.sign 而不是使用条件:

    df[columns] = df[columns].apply(lambda x: np.power(np.absolute(x), 1./3) * np.sign(x))
    

    这会计算绝对值的立方根,然后适当地更改符号。

    【讨论】:

    • 我应该寻找立方根特定函数 :-) 不错的答案!
    【解决方案3】:

    试试:

    sample[columns]=sample[columns]**(1/3)
    

    【讨论】:

    • 不幸的是,这种方法不适用于负值。
    • @amirtZ 确实没有,你能提供一个重现错误的代码吗?
    • 也不确定您指的是什么代码。但是在数据帧上运行原始代码会给出:“数据帧的真值是模棱两可的。使用 a.empty()、a.bool()、a.item()、a.any() 或 a.all() 。”
    • 就像发布一个示例数据框,人们可以运行,看到未来的问题,人们更容易解决它。很高兴@piRsquared 仍然可以解决您的问题,如果您只对值进行操作而不管索引/列如何,最好使用 applymap,因为每次应用都返回一个系列的副本而不是一个标量,所以速度更快。
    猜你喜欢
    • 1970-01-01
    • 2017-04-15
    • 2015-01-18
    • 2018-04-25
    • 2012-09-09
    • 1970-01-01
    • 2023-02-04
    • 2020-04-09
    • 2014-02-15
    相关资源
    最近更新 更多