MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python数值列表的简单统计计算

2022-07-163.6k 阅读

数值列表在Python中的基础概念

在Python编程中,数值列表是一种常见的数据结构,它允许我们将多个数值元素组合在一起进行统一的管理和操作。列表是Python中的一种可变序列,通过方括号 [] 来定义,其中的元素可以是不同类型的数据,但在进行数值相关的统计计算时,通常会处理仅包含数值类型(如整数 int 或浮点数 float)的列表。

例如,以下是一个简单的数值列表:

nums = [1, 2, 3, 4, 5]

这个列表 nums 包含了五个整数元素。

列表的创建与初始化

  1. 直接赋值法:这是最常见的创建数值列表的方式,如上述示例,直接在方括号内列出数值元素。
num_list = [10, 20, 30, 40]
  1. 使用 range() 函数range() 函数可以生成一个整数序列,常用来初始化数值列表。它有三种使用形式:
    • range(stop):生成从 0stop - 1 的整数序列。
seq1 = list(range(5))
print(seq1)  
- `range(start, stop)`:生成从 `start` 到 `stop - 1` 的整数序列。
seq2 = list(range(1, 6))
print(seq2)  
- `range(start, stop, step)`:生成从 `start` 到 `stop - 1` 的整数序列,步长为 `step`。
seq3 = list(range(1, 10, 2))
print(seq3)  
  1. 列表推导式:这是一种简洁的创建列表的方式,尤其适用于根据已有序列或规则生成新的数值列表。 例如,生成一个包含 110 每个数平方的列表:
squares = [num ** 2 for num in range(1, 11)]
print(squares)  

基本统计计算

求和

在Python中,计算数值列表的总和是一个常见的操作。Python提供了内置函数 sum() 来完成这个任务。

nums = [1, 2, 3, 4, 5]
total = sum(nums)
print(total)  

sum() 函数会遍历列表中的每个元素,并将它们相加,返回最终的总和。如果列表为空,sum() 函数将返回 0

求平均值

计算平均值需要先求出总和,再除以元素的个数。结合 sum() 函数和 len() 函数(用于获取列表的长度)可以很容易地实现。

nums = [1, 2, 3, 4, 5]
total = sum(nums)
count = len(nums)
average = total / count
print(average)  

在处理浮点数时,由于浮点数运算的精度问题,可能会得到一个接近真实值但有微小偏差的结果。例如:

nums = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
total = sum(nums)
count = len(nums)
average = total / count
print(average)  

这里输出的结果可能不是精确的 0.1,而是一个非常接近 0.1 的值,如 0.09999999999999999。在对精度要求较高的场景下,可以使用 decimal 模块。

求最大值和最小值

Python提供了内置函数 max()min() 来获取数值列表中的最大值和最小值。

nums = [1, 5, 3, 9, 7]
max_num = max(nums)
min_num = min(nums)
print(max_num)  
print(min_num)  

如果列表为空,调用 max()min() 函数会引发 ValueError 异常。

中位数计算

中位数是将一组数据按照大小顺序排列后,处于中间位置的数值。如果数据个数为奇数,中位数就是中间的那个数;如果数据个数为偶数,中位数是中间两个数的平均值。

排序法求中位数

  1. 首先,我们需要对列表进行排序。Python列表有一个 sort() 方法,或者可以使用内置函数 sorted(),前者会修改原列表,后者返回一个新的已排序列表。
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
sorted_nums = sorted(nums)
count = len(sorted_nums)
if count % 2 == 0:
    mid1 = sorted_nums[count // 2 - 1]
    mid2 = sorted_nums[count // 2]
    median = (mid1 + mid2) / 2
else:
    median = sorted_nums[count // 2]
print(median)  
  1. 使用 statistics 模块求中位数 Python的 statistics 模块提供了更方便的方法来计算中位数。
import statistics
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
try:
    median = statistics.median(nums)
    print(median)  
except statistics.StatisticsError as e:
    print(f"Error: {e}")  

statistics.median() 函数会自动处理数据个数为奇数或偶数的情况,并返回准确的中位数。如果列表为空,会抛出 StatisticsError 异常。

方差和标准差计算

方差和标准差是衡量数据离散程度的重要统计量。方差表示每个数据与平均数的差的平方的平均数,标准差是方差的平方根。

手动计算方差和标准差

  1. 计算方差:
nums = [1, 2, 3, 4, 5]
total = sum(nums)
count = len(nums)
average = total / count
squared_diff_sum = sum((num - average) ** 2 for num in nums)
variance = squared_diff_sum / count
print(variance)  
  1. 计算标准差:
import math
nums = [1, 2, 3, 4, 5]
total = sum(nums)
count = len(nums)
average = total / count
squared_diff_sum = sum((num - average) ** 2 for num in nums)
variance = squared_diff_sum / count
std_deviation = math.sqrt(variance)
print(std_deviation)  

使用 statistics 模块计算方差和标准差

statistics 模块提供了 variance()stdev() 函数来计算方差和标准差。

import statistics
nums = [1, 2, 3, 4, 5]
try:
    variance = statistics.variance(nums)
    std_deviation = statistics.stdev(nums)
    print(variance)  
    print(std_deviation)  
except statistics.StatisticsError as e:
    print(f"Error: {e}")  

这里的 variance()stdev() 函数在处理样本数据时,默认使用的是无偏估计(分母为 n - 1)。如果要计算总体方差和标准差,可以设置 statistics.variance(data, xbar=None)statistics.stdev(data, xbar=None) 中的 xbar 参数为总体均值,并且函数会使用 n 作为分母进行计算。

百分位数计算

百分位数是一种位置统计量,它表示在一组数据中有一定百分比的数据小于或等于该值。例如,第25百分位数(也称为第一四分位数 Q1)表示有25%的数据小于或等于该值。

使用 numpy 库计算百分位数

虽然Python标准库没有直接提供计算百分位数的函数,但 numpy 库提供了强大的支持。首先需要安装 numpy,可以使用 pip install numpy 命令。

import numpy as np
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
percentile_25 = np.percentile(nums, 25)
percentile_50 = np.percentile(nums, 50)
percentile_75 = np.percentile(nums, 75)
print(percentile_25)  
print(percentile_50)  
print(percentile_75)  

np.percentile() 函数的第一个参数是数据列表,第二个参数是要计算的百分位数(0到100之间)。

手动近似计算百分位数

手动计算百分位数需要先对数据进行排序,然后根据公式确定百分位数的位置。假设数据个数为 n,要计算第 p 百分位数,位置 L = (n - 1) * p / 100。如果 L 是整数,则第 p 百分位数是第 LL + 1 位置数据的平均值;如果 L 不是整数,则向上取整得到位置索引。

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sorted_nums = sorted(nums)
n = len(sorted_nums)
p = 25
L = (n - 1) * p / 100
if L.is_integer():
    percentile = (sorted_nums[int(L)] + sorted_nums[int(L) + 1]) / 2
else:
    percentile = sorted_nums[int(L) + 1]
print(percentile)  

这种手动计算方法是一种近似,与 numpy 库提供的精确计算方法在一些情况下可能会有细微差异。

协方差和相关系数计算

协方差和相关系数用于衡量两个变量之间的线性关系。

手动计算协方差和相关系数

  1. 计算协方差: 假设我们有两个数值列表 xy,协方差计算公式为: [Cov(X,Y)=\frac{1}{n}\sum_{i = 1}^{n}(x_i-\bar{x})(y_i-\bar{y})]
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]
n = len(x)
x_mean = sum(x) / n
y_mean = sum(y) / n
covariance = sum((x[i] - x_mean) * (y[i] - y_mean) for i in range(n)) / n
print(covariance)  
  1. 计算相关系数: 相关系数是协方差除以两个变量标准差的乘积,公式为: [\rho_{X,Y}=\frac{Cov(X,Y)}{\sigma_X\sigma_Y}]
import math
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]
n = len(x)
x_mean = sum(x) / n
y_mean = sum(y) / n
x_squared_diff_sum = sum((x_i - x_mean) ** 2 for x_i in x)
y_squared_diff_sum = sum((y_i - y_mean) ** 2 for y_i in y)
x_std_dev = math.sqrt(x_squared_diff_sum / n)
y_std_dev = math.sqrt(y_squared_diff_sum / n)
covariance = sum((x[i] - x_mean) * (y[i] - y_mean) for i in range(n)) / n
correlation_coefficient = covariance / (x_std_dev * y_std_dev)
print(correlation_coefficient)  

使用 numpy 库计算协方差和相关系数

numpy 库提供了更方便的函数来计算协方差和相关系数。

  1. 计算协方差矩阵:
import numpy as np
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]
data = np.vstack((x, y))
covariance_matrix = np.cov(data)
print(covariance_matrix)  

协方差矩阵的对角线上是各个变量的方差,非对角线上是变量之间的协方差。 2. 计算相关系数矩阵:

import numpy as np
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]
data = np.vstack((x, y))
correlation_matrix = np.corrcoef(data)
print(correlation_matrix)  

相关系数矩阵的对角线上都是 1,表示变量自身与自身的相关系数为 1,非对角线上是变量之间的相关系数。

统计计算中的数据类型问题

在进行数值列表的统计计算时,数据类型的一致性非常重要。如果列表中包含不同类型的数据,例如同时包含整数和字符串,可能会导致运行时错误。

nums = [1, '2', 3]
try:
    total = sum(nums)
except TypeError as e:
    print(f"Error: {e}")  

这里会抛出 TypeError 异常,因为 sum() 函数无法对整数和字符串进行相加操作。在实际应用中,需要确保列表中的元素类型一致,通常是 intfloat 类型。

另外,在处理浮点数时,由于浮点数的表示和运算精度问题,可能会出现一些意想不到的结果。例如,在比较两个浮点数是否相等时,不能直接使用 == 运算符,而应该使用一个微小的误差范围(epsilon)来进行比较。

a = 0.1 + 0.1 + 0.1
b = 0.3
if abs(a - b) < 1e-9:
    print("They are equal within a small tolerance.")
else:
    print("They are not equal.")  

这里使用 abs() 函数获取两个数的差值的绝对值,并与一个非常小的数 1e - 9 进行比较,以判断它们在一个可接受的误差范围内是否相等。

性能优化

在处理大规模数值列表的统计计算时,性能优化是一个重要的考虑因素。

使用 numpy 库提升性能

numpy 库是专门为处理数值计算而设计的,它在底层使用了高效的C语言实现,因此在处理大规模数据时比纯Python代码快得多。例如,计算数值列表的总和:

import numpy as np
nums = list(range(1000000))
# 使用Python内置sum函数
import time
start_time = time.time()
total_python = sum(nums)
python_time = time.time() - start_time
# 使用numpy的sum函数
nums_np = np.array(nums)
start_time = time.time()
total_numpy = np.sum(nums_np)
numpy_time = time.time() - start_time
print(f"Python sum time: {python_time}")
print(f"numpy sum time: {numpy_time}")  

可以看到,对于大规模数据,numpysum() 函数比Python内置的 sum() 函数快很多。

减少中间数据的生成

在进行统计计算时,尽量避免生成过多不必要的中间数据。例如,在计算方差时,直接在循环中累加平方差,而不是先生成一个包含所有平方差的列表再求和。

nums = [1, 2, 3, 4, 5]
total = sum(nums)
count = len(nums)
average = total / count
squared_diff_sum = 0
for num in nums:
    squared_diff_sum += (num - average) ** 2
variance = squared_diff_sum / count
print(variance)  

这种方法避免了生成一个包含所有平方差的中间列表,从而节省了内存和时间。

使用生成器表达式

生成器表达式是一种惰性求值的方式,可以在需要时才生成数据,而不是一次性生成所有数据。例如,在计算总和时,可以使用生成器表达式:

nums = [1, 2, 3, 4, 5]
total = sum((num for num in nums))
print(total)  

这里的 (num for num in nums) 就是一个生成器表达式,它不会立即生成一个新的列表,而是在 sum() 函数需要数据时逐个生成。

异常处理

在进行数值列表的统计计算时,可能会遇到各种异常情况,需要进行适当的异常处理以确保程序的稳定性。

处理空列表异常

如前面提到的,在调用 max()min()sum() 等函数时,如果列表为空会引发异常。可以使用 try - except 语句来捕获并处理这些异常。

nums = []
try:
    max_num = max(nums)
except ValueError as e:
    print(f"Error: {e}")  

处理类型错误异常

当列表中包含不适当的数据类型,如字符串和数值混合时,会引发 TypeError 异常。同样可以使用 try - except 语句处理。

nums = [1, '2', 3]
try:
    total = sum(nums)
except TypeError as e:
    print(f"Error: {e}")  

通过合理的异常处理,可以使程序在遇到意外情况时不会崩溃,而是给出有意义的错误提示或采取其他适当的措施。

在Python中对数值列表进行统计计算,不仅有丰富的内置函数和模块支持,还可以通过第三方库如 numpy 来提升性能和功能。在实际应用中,需要根据具体需求选择合适的方法,并注意数据类型、性能优化和异常处理等方面的问题,以编写出高效、稳定的代码。