假设我有一个Pandas系列s
,它的值和1
,并且它的值都大于或等于0
。我需要从所有值中减去一个常数,这样新序列的和就等于0.6
。问题是,当我减去这个常数时,值永远不会小于零。你知道吗
在数学公式中,假设我有一系列的x
,我想找到k
import pandas as pd
import numpy as np
from string import ascii_uppercase
np.random.seed([3, 141592653])
s = np.power(
1000, pd.Series(
np.random.rand(10),
list(ascii_uppercase[:10])
)
).pipe(lambda s: s / s.sum())
s
A 0.001352
B 0.163135
C 0.088365
D 0.010904
E 0.007615
F 0.407947
G 0.005856
H 0.198381
I 0.027455
J 0.088989
dtype: float64
总和是1
s.sum()
0.99999999999999989
我可以使用Scipy的optimize
模块中的Newton方法
from scipy.optimize import newton
def f(k):
return s.sub(k).clip(0).sum() - .6
找到这个函数的根将为我提供所需的k
initial_guess = .1
k = newton(f, x0=initial_guess)
然后从s
中减去这个
new_s = s.sub(k).clip(0)
new_s
A 0.000000
B 0.093772
C 0.019002
D 0.000000
E 0.000000
F 0.338583
G 0.000000
H 0.129017
I 0.000000
J 0.019626
dtype: float64
新的总数是
new_s.sum()
0.60000000000000009
我们能不借助解算器找到k
吗?你知道吗
一个精确解,只需要一个排序,然后在O(n)中(好吧,更少:我们只需要与将变为零的值的数量一样多的循环):
我们尽可能将最小值变为零,然后在其余值之间共享剩余的多余值:
我没料到
newton
会占上风。但在大型阵列上,确实如此。你知道吗numba.njit
受Thierry'sAnswer启发
在具有
numba
sjit
的排序数组上使用循环numpy
灵感来自Paul'sAnswer
抬重物的小家伙。你知道吗
scipy.optimize.newton
我的牛顿法
计时赛
结果
更新:三种不同的实现-有趣的是,最不复杂的可扩展性最好。你知道吗
运行示例:
相关问题 更多 >
编程相关推荐