如何制作一个连续包含 numpy 数组的另一个元素的循环以计算 运行 方差?
How to make a loop that successively includes one more element of a numpy array in order to calculate the running variance?
我将数字存储在数组中,例如 [1, 6, 12, 4...]
。我想做一个计算,其中每个新迭代将使用数组的一个元素。
- 例如,第一次迭代将仅使用数字
1
。
- 第二次迭代将使用
1
和 6
。
- 第三个将使用
1
、6
和12
,依此类推。
任何对 Python 中的 statistics/variance 感兴趣的人的详细信息:
我想计算数组中数据的 运行 方差。在 Python 中获取整个数组的方差似乎很简单。所以我将我的数组放在循环中直到元素 i
。我将随着循环的进行和数组计算方差 "grows." 如果有人知道更好的方法,我将不胜感激。
您可以使用slices:
>>>> seq = [1, 2, 3, 4]
>>>> for i in range(len(seq)):
.... print(sum(seq[:i+1]))
....
1
3
6
10
希望对您有所帮助。
根据您想要的效率,您可以采用不同的方式。
最直接的就是用切片求和到当前值:
ls = [1, 6, 12, 4]
for i in range(len(ls)):
print(sum(ls[:i+1]))
但是您会发现,随着时间的推移,累加器模式会表现得更好。下面的代码删除了对 sum
的调用,将循环的计算复杂度降低到 O(n)。它在包含数十万个项目的大型数据集上的执行速度应该明显更快:
ls = [1, 6, 12, 4]
total = 0
for item in ls:
total += item
print(total)
这是一个很常见的模式,可以很方便地创建一个可重用的函数。下面的代码可以让您用其他行为替换 foo
行为:
def accumulate(fn, iterable):
total = 0
for i, item in iterable:
total = fn(i, item, total)
def foo(i, item, total):
print(f'The running total is {total}.')
return total + 2 * item - i
accumulate(foo, [1, 6, 12, 4])
>>> The running total is 2.
>>> The running total is 13.
>>> The running total is 35.
>>> The running total is 40.
为了计算 numpy 数组的 运行ning 方差,您可以在列表理解中使用切片,如下所示:
import numpy as np
a = [1, 6, 12, 4]
running_var = [np.var(a[:i+1]) for i in range(len(a))]
print(running_var)
#[0.0, 6.25, 20.222222222222225, 16.1875]
但是随着您的列表变大,您将浪费计算。一种更有效的方法是跟踪 a
中值的 运行ning 和以及 a
.[=20= 的平方和 运行ning ]
running_sum = 0.
running_sum_of_squares = 0.
running_var = []
for i,x in enumerate(a):
running_sum += x
running_sum_of_squares += x*x
n = i+1.
running_var.append((running_sum_of_squares - running_sum*running_sum/n)/n)
print(running_var)
#[0.0, 6.25, 20.222222222222225, 16.1875]
此计算针对的是总体方差,但您可以针对样本方差轻松调整它。
计时结果
为了展示第二种方法的巨大速度提升,这里是一个时间比较:
创建大型随机样本
np.random.seed(0)
N = 100000
a = np.random.randn(N)
方法一:列表理解
%%timeit
running_var = [np.var(a[:i+1]) for i in range(len(a))]
# 1 loop, best of 3: 11.1 s per loop
方法二:增量方差计算
def get_running_var(a):
running_sum = 0.
running_sum_of_squares = 0.
running_var = []
for i,x in enumerate(a):
running_sum += x
running_sum_of_squares += x*x
n = i+1.
running_var.append((running_sum_of_squares - running_sum*running_sum/n)/n)
return running_var
%%timeit
get_running_var(a)
# 10 loops, best of 3: 60.5 ms per loop
10万大小的数组,增量计算快180多倍!
由于 MemoryError
,我无法 运行 使用 N = 100000
在 @user3483203's answer 上进行速度测试,因此我对大小为 10,000 的数组重复了测试.
结果如下:
- 列表理解:100 次循环,最好的 3 次:每次循环 268 毫秒
- 增量方差:100 次循环,最好的 3 次:每次循环 6.09 毫秒
- user3483203 的方法:1 个循环,3 个中的最佳:每个循环 5.73 秒
我将数字存储在数组中,例如 [1, 6, 12, 4...]
。我想做一个计算,其中每个新迭代将使用数组的一个元素。
- 例如,第一次迭代将仅使用数字
1
。 - 第二次迭代将使用
1
和6
。 - 第三个将使用
1
、6
和12
,依此类推。
任何对 Python 中的 statistics/variance 感兴趣的人的详细信息:
我想计算数组中数据的 运行 方差。在 Python 中获取整个数组的方差似乎很简单。所以我将我的数组放在循环中直到元素 i
。我将随着循环的进行和数组计算方差 "grows." 如果有人知道更好的方法,我将不胜感激。
您可以使用slices:
>>>> seq = [1, 2, 3, 4]
>>>> for i in range(len(seq)):
.... print(sum(seq[:i+1]))
....
1
3
6
10
希望对您有所帮助。
根据您想要的效率,您可以采用不同的方式。
最直接的就是用切片求和到当前值:
ls = [1, 6, 12, 4]
for i in range(len(ls)):
print(sum(ls[:i+1]))
但是您会发现,随着时间的推移,累加器模式会表现得更好。下面的代码删除了对 sum
的调用,将循环的计算复杂度降低到 O(n)。它在包含数十万个项目的大型数据集上的执行速度应该明显更快:
ls = [1, 6, 12, 4]
total = 0
for item in ls:
total += item
print(total)
这是一个很常见的模式,可以很方便地创建一个可重用的函数。下面的代码可以让您用其他行为替换 foo
行为:
def accumulate(fn, iterable):
total = 0
for i, item in iterable:
total = fn(i, item, total)
def foo(i, item, total):
print(f'The running total is {total}.')
return total + 2 * item - i
accumulate(foo, [1, 6, 12, 4])
>>> The running total is 2.
>>> The running total is 13.
>>> The running total is 35.
>>> The running total is 40.
为了计算 numpy 数组的 运行ning 方差,您可以在列表理解中使用切片,如下所示:
import numpy as np
a = [1, 6, 12, 4]
running_var = [np.var(a[:i+1]) for i in range(len(a))]
print(running_var)
#[0.0, 6.25, 20.222222222222225, 16.1875]
但是随着您的列表变大,您将浪费计算。一种更有效的方法是跟踪 a
中值的 运行ning 和以及 a
.[=20= 的平方和 运行ning ]
running_sum = 0.
running_sum_of_squares = 0.
running_var = []
for i,x in enumerate(a):
running_sum += x
running_sum_of_squares += x*x
n = i+1.
running_var.append((running_sum_of_squares - running_sum*running_sum/n)/n)
print(running_var)
#[0.0, 6.25, 20.222222222222225, 16.1875]
此计算针对的是总体方差,但您可以针对样本方差轻松调整它。
计时结果
为了展示第二种方法的巨大速度提升,这里是一个时间比较:
创建大型随机样本
np.random.seed(0)
N = 100000
a = np.random.randn(N)
方法一:列表理解
%%timeit
running_var = [np.var(a[:i+1]) for i in range(len(a))]
# 1 loop, best of 3: 11.1 s per loop
方法二:增量方差计算
def get_running_var(a):
running_sum = 0.
running_sum_of_squares = 0.
running_var = []
for i,x in enumerate(a):
running_sum += x
running_sum_of_squares += x*x
n = i+1.
running_var.append((running_sum_of_squares - running_sum*running_sum/n)/n)
return running_var
%%timeit
get_running_var(a)
# 10 loops, best of 3: 60.5 ms per loop
10万大小的数组,增量计算快180多倍!
由于 MemoryError
,我无法 运行 使用 N = 100000
在 @user3483203's answer 上进行速度测试,因此我对大小为 10,000 的数组重复了测试.
结果如下:
- 列表理解:100 次循环,最好的 3 次:每次循环 268 毫秒
- 增量方差:100 次循环,最好的 3 次:每次循环 6.09 毫秒
- user3483203 的方法:1 个循环,3 个中的最佳:每个循环 5.73 秒