第三讲:核心数据科学库入门
各位风电投资的朋友们,大家好。今天我们来聊聊数据科学三剑客——NumPy、Pandas 和 Matplotlib。说实话,这三个库是咱们做风电投资分析的“吃饭家伙”。你想想看,从风机数据清洗到收益率计算,再到最后的可视化汇报,哪一步都离不开它们。
3.1 NumPy 数组操作:风电数据的“骨架”
NumPy 的核心就是数组。我刚开始做风电项目时,习惯用 Python 列表存风速数据,结果一算几十万条数据的平均值,慢得让人抓狂。后来换成 NumPy 数组,速度直接提升几十倍。为什么?因为 NumPy 底层是 C 语言实现的,而且数组元素类型统一,计算时能批量处理。
3.1.1 创建数组
咱们先看怎么创建数组。最常用的就是 np.array(),直接把列表传进去就行。
import numpy as np
# 从列表创建一维数组
wind_speed = np.array([5.2, 6.8, 7.1, 4.9, 8.3])
print(wind_speed) # 输出:[5.2 6.8 7.1 4.9 8.3]
# 创建全零数组,比如初始化一个月的日发电量
daily_power = np.zeros(30)
print(daily_power) # 30个0.0
# 创建等间隔数组,比如模拟风速从3到25m/s
wind_range = np.linspace(3, 25, 10)
print(wind_range) # 输出10个等间隔点
嗯,这里要注意:np.linspace 默认包含终点,而 np.arange 不包含终点。我在项目中吃过这个亏,画功率曲线时少了一个点,曲线就不连续了。
3.1.2 数组运算:向量化操作
NumPy 最爽的地方就是向量化运算。你不用写循环,直接对整个数组做数学运算。
# 风速数据(m/s)
wind = np.array([5, 7, 9, 6, 8])
# 计算风功率密度(简化公式:0.5 * 空气密度 * v^3)
air_density = 1.225 # kg/m³
power_density = 0.5 * air_density * wind ** 3
print(power_density) # 直接得到每个风速对应的功率密度
# 布尔索引:筛选出风速大于6m/s的数据
high_wind = wind[wind > 6]
print(high_wind) # 输出:[7 9 8]
我个人习惯用布尔索引做数据筛选,比如找出所有“切出风速”以上的异常数据。曾经有个项目,现场传回的数据里混了几个 99.9 的异常值,用 data[data < 25] 一下就过滤掉了。
3.1.3 数组形状操作
风电数据经常是多维的。比如一个风电场有 10 台风机,每台记录 365 天的发电量,那就是一个 10×365 的二维数组。
# 创建二维数组
data = np.array([[1, 2, 3], [4, 5, 6]])
print(data.shape) # 输出:(2, 3)
# 重塑形状:把一维变成二维
flat = np.arange(12)
matrix = flat.reshape(3, 4) # 变成3行4列
print(matrix)
# 转置:行变列,列变行
transposed = matrix.T
print(transposed.shape) # 输出:(4, 3)
np.resize 自动补齐或截断。
3.2 Pandas 数据处理:风电投资的“瑞士军刀”
如果说 NumPy 是骨架,那 Pandas 就是血肉。它提供了 DataFrame 和 Series 两种数据结构,专门处理表格型数据。咱们做风电投资,数据来源五花八门:SCADA 系统导出的 CSV、气象局给的 Excel、甚至手工录入的纸质台账。Pandas 都能搞定。
3.2.1 读取数据
import pandas as pd
# 读取CSV文件(最常见)
df = pd.read_csv('wind_farm_data.csv')
print(df.head()) # 查看前5行
# 读取Excel文件
df_excel = pd.read_excel('project_finance.xlsx', sheet_name='现金流')
# 从字典创建DataFrame
data_dict = {
'风机编号': ['WTG01', 'WTG02', 'WTG03'],
'额定功率(kW)': [2000, 2000, 2500],
'年发电量(MWh)': [4800, 5100, 6200]
}
df = pd.DataFrame(data_dict)
print(df)
我记得有一次,现场给的 CSV 文件编码是 GBK,直接读出来全是乱码。加个参数 encoding='gbk' 就解决了。嗯,这种坑遇到一次就记住了。
3.2.2 数据清洗:处理缺失值和异常值
实际项目中的数据很少是干净的。风机停机、传感器故障、通讯中断,都会产生缺失值。
# 检查缺失值
print(df.isnull().sum())
# 删除含有缺失值的行
df_clean = df.dropna()
# 填充缺失值(比如用平均值填充)
df['风速'].fillna(df['风速'].mean(), inplace=True)
# 处理异常值:风速不可能大于30m/s
df = df[df['风速'] <= 30]
3.2.3 数据分组与聚合
风电投资分析中,经常需要按时间、按机组、按区域做汇总。
# 按月份分组,计算月平均风速
df['日期'] = pd.to_datetime(df['日期'])
df['月份'] = df['日期'].dt.month
monthly_avg = df.groupby('月份')['风速'].mean()
print(monthly_avg)
# 多列聚合:同时计算平均值和标准差
agg_result = df.groupby('风机编号').agg({
'风速': ['mean', 'std'],
'发电量': 'sum'
})
print(agg_result)
我个人习惯用 groupby 配合 agg,一次算出多个统计量。比如评估不同机型的经济性,我会按机型分组,计算平均发电量、标准差和容量因子,一张表就看清了。
3.2.4 时间序列处理
风电数据天然是时间序列。Pandas 的时间序列功能非常强大。
# 设置日期为索引
df.set_index('日期', inplace=True)
# 重采样:从小时数据重采样为日数据
daily_data = df.resample('D').mean()
# 滚动窗口:计算7天移动平均
df['风速_7日均线'] = df['风速'].rolling(window=7).mean()
# 时间偏移:计算滞后1小时的风速
df['风速_滞后1h'] = df['风速'].shift(1)
3.3 Matplotlib 基础绘图:让数据“说话”
数据算完了,怎么呈现给投资人?Matplotlib 就是干这个的。我见过太多人用 Excel 画图,说实话,那效果和专业报告差远了。用 Matplotlib 画出来的图,清晰、可定制、还能批量生成。
3.3.1 折线图:展示趋势
import matplotlib.pyplot as plt
# 简单折线图:日发电量趋势
days = range(1, 31)
power = [120, 135, 110, 150, 140, 130, 125, 145, 155, 160,
140, 130, 120, 115, 125, 135, 145, 150, 140, 130,
120, 110, 105, 115, 125, 135, 140, 145, 150, 155]
plt.figure(figsize=(10, 5))
plt.plot(days, power, marker='o', linestyle='-', color='blue')
plt.title('某风电场日发电量趋势')
plt.xlabel('日期(天)')
plt.ylabel('发电量(MWh)')
plt.grid(True, alpha=0.3)
plt.show()
嗯,这里要注意:plt.show() 在 Jupyter Notebook 里可以省略,但在脚本里必须写。我曾经在服务器上跑脚本,忘了加 plt.show(),结果图没保存下来,白跑了一夜。
3.3.2 散点图:看相关性
# 风速与发电量的散点图
wind_speed = np.random.normal(8, 2, 100) # 模拟风速
power_output = 0.4 * wind_speed ** 3 + np.random.normal(0, 50, 100) # 模拟发电量
plt.figure(figsize=(8, 6))
plt.scatter(wind_speed, power_output, alpha=0.6, color='green')
plt.title('风速与发电量关系')
plt.xlabel('风速(m/s)')
plt.ylabel('发电量(kW)')
plt.grid(True, alpha=0.3)
plt.show()
你看这个散点图,能明显看出风速和发电量不是线性关系,而是接近三次方关系。这就是为什么我们做投资测算时,要用功率曲线而不是简单线性回归。
3.3.3 柱状图:对比分析
# 不同机型年发电量对比
models = ['机型A', '机型B', '机型C', '机型D']
annual_energy = [4800, 5200, 6100, 5500]
plt.figure(figsize=(8, 5))
plt.bar(models, annual_energy, color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'])
plt.title('不同机型年发电量对比')
plt.ylabel('年发电量(MWh)')
for i, v in enumerate(annual_energy):
plt.text(i, v + 50, str(v), ha='center')
plt.show()
plt.text 加标签,位置稍微抬高一点,避免被柱子挡住。
3.3.4 子图:多图组合
做投资报告时,经常需要把多个图放在一起对比。
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 左上:折线图
axes[0, 0].plot(days, power, color='blue')
axes[0, 0].set_title('日发电量趋势')
# 右上:散点图
axes[0, 1].scatter(wind_speed, power_output, alpha=0.6, color='green')
axes[0, 1].set_title('风速与发电量关系')
# 左下:柱状图
axes[1, 0].bar(models, annual_energy, color='orange')
axes[1, 0].set_title('机型对比')
# 右下:饼图(展示容量占比)
capacity = [30, 25, 20, 25]
axes[1, 1].pie(capacity, labels=models, autopct='%1.1f%%')
axes[1, 1].set_title('装机容量占比')
plt.tight_layout()
plt.show()
3.4 知识体系总览
下面这张图,是我自己总结的这三个库在风电投资分析中的定位。你看一眼就能明白它们各自负责什么。
说白了,这三个库是层层递进的关系。NumPy 负责底层的高性能计算,Pandas 负责中间层的数据清洗和分析,Matplotlib 负责最终的可视化呈现。你想想看,从原始的风速数据到最终的投资决策报告,每一步都离不开它们。
好了,这一讲的内容就到这里。记住,工具是死的,但思路是活的。下次遇到风电投资问题,先想想:数据从哪里来?用什么库处理?最终要呈现什么结果?想清楚了再动手。