引言:为什么Python数据分析是职场必备技能?

在当今数据驱动的商业环境中,Python已经成为数据分析领域的绝对主流工具。根据最新的行业调查,超过85%的数据分析师使用Python作为主要编程语言。这不仅仅是因为Python语法简洁易学,更重要的是它拥有强大的生态系统,特别是pandas、numpy和matplotlib/seaborn这三大核心库,它们构成了数据分析的”黄金三角”。

对于想要提升职场竞争力的专业人士来说,掌握Python数据分析意味着:

  • 效率提升:自动化重复性数据处理工作,将原本需要数小时的工作缩短到几分钟
  • 洞察力增强:通过高级分析技术发现数据中隐藏的商业价值
  • 决策支持:用数据驱动的洞察为管理层提供可靠的决策依据
  • 职业发展:根据LinkedIn数据,具备Python数据分析技能的专业人士平均薪资比同行高出30-50%

本课程将带你从基础入门到精通,系统掌握pandas、numpy和可视化技巧,解决实际工作中的数据清洗与分析难题。

第一部分:NumPy基础与进阶——高效数值计算的基石

NumPy核心概念:ndarray数组

NumPy是Python科学计算的基础库,它提供了高性能的多维数组对象和相关的操作。理解ndarray是掌握NumPy的关键。

import numpy as np

# 创建不同类型的数组
# 1. 从列表创建数组
arr1 = np.array([1, 2, 3, 4, 5])
print(f"一维数组: {arr1}")
print(f"数组类型: {type(arr1)}")
print(f"数组形状: {arr1.shape}")
print(f"数组维度: {arr1.ndim}")

# 2. 创建特殊数组
zeros_arr = np.zeros((3, 4))  # 3行4列的零矩阵
ones_arr = np.ones((2, 3))    # 2行3列的单位矩阵
identity_arr = np.eye(3)      # 3x3单位矩阵
range_arr = np.arange(0, 10, 2)  # 等差数列: 0,2,4,6,8
linspace_arr = np.linspace(0, 1, 5)  # 0到1之间等分5个点

print("\n特殊数组示例:")
print("零矩阵:\n", zeros_arr)
print("单位矩阵:\n", identity_arr)
print("等差数列:", range_arr)
print("等分点:", linspace_arr)

# 3. 随机数组
random_arr = np.random.rand(3, 3)  # 0-1均匀分布
normal_arr = np.random.randn(3, 3) # 标准正态分布
int_arr = np.random.randint(0, 10, (3, 3))  # 0-10随机整数

print("\n随机数组:\n", random_arr)

NumPy数组操作与索引

# 数组索引和切片
arr = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12]])

# 基本索引
print("第2行:", arr[1])      # 索引从0开始
print("第3列:", arr[:, 2])   # 所有行,第3列
print("第2行第3列:", arr[1, 2])

# 切片操作
print("前两行:\n", arr[:2, :])
print("第2-3列:\n", arr[:, 1:3])
print("逆序:\n", arr[::-1, ::-1])

# 布尔索引
bool_idx = arr > 5
print("大于5的元素:\n", arr[bool_idx])
print("大于5的元素个数:", np.sum(arr > 5))

# 花式索引
indices = [0, 2]  # 选择第0行和第2行
print("选择指定行:\n", arr[indices])

# 形状变换
reshaped = arr.reshape(4, 3)
print("重塑形状(4,3):\n", reshaped)

# 数组拼接
arr2 = np.array([[13, 14, 15, 16]])
vertical = np.vstack((arr, arr2))  # 垂直拼接
horizontal = np.hstack((arr, arr.T))  # 水平拼接

print("垂直拼接:\n", vertical)
print("水平拼接:\n", horizontal)

NumPy广播机制与向量化运算

广播是NumPy最强大的特性之一,它允许不同形状的数组进行算术运算。

# 广播机制示例
a = np.array([1, 2, 3, 4])
b = 2  # 标量

# 标量与数组运算(广播)
result = a + b
print(f"a + b = {result}")  # [3,4,5,6]

# 数组与数组运算
arr1 = np.array([[1, 2, 3],
                 [4, 5, 6]])
arr2 = np.array([10, 20, 30])  # 形状(3,),广播到(2,3)

result = arr1 + arr2
print("数组广播加法:\n", result)

# 不同形状的广播
arr3 = np.array([[1], [2], [3]])  # 形状(3,1)
arr4 = np.array([10, 20, 30, 40])  # 形状(4,)

# 广播结果为(3,4)
result = arr3 + arr4
print("复杂广播:\n", result)

# 向量化运算 vs 循环
import time

# 循环方式
def loop_multiply(arr, scalar):
    result = np.zeros_like(arr)
    for i in range(arr.shape[0]):
        for j in range(arr.shape[1]):
            result[i, j] = arr[i, j] * scalar
    return result

# 向量化方式
def vectorized_multiply(arr, scalar):
    return arr * scalar

# 性能对比
large_arr = np.random.rand(1000, 1000)
scalar = 2.5

start = time.time()
loop_result = loop_multiply(large_arr, scalar)
loop_time = time.time() - start

start = time.time()
vectorized_result = vectorized_multiply(large_arr, scalar)
vectorized_time = time.time() - start

print(f"循环方式耗时: {loop_time:.4f}秒")
print(f"向量化方式耗时: {vectorized_time:.4f}秒")
print(f"性能提升: {loop_time/vectorized_time:.1f}倍")

NumPy高级数学运算

# 统计运算
arr = np.random.randn(5, 5) * 10  # 5x5随机数组,放大10倍

print("原始数组:\n", arr)
print(f"平均值: {np.mean(arr):.2f}")
print(f"中位数: {np.median(arr):.2f}")
print(f"标准差: {np.std(arr):.2f}")
print(f"方差: {np.var(arr):.2f}")
print(f"最小值: {np.min(arr):.2f}")
print(f"最大值: {np.max(arr):.2f}")

# 沿轴运算
print("\n沿轴运算:")
print("每行平均值:", np.mean(arr, axis=1))
print("每列平均值:", np.mean(arr, axis=0))

# 线性代数
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

# 矩阵乘法
C = np.dot(A, B)  # 或者 A @ B
print("\n矩阵乘法:\n", C)

# 矩阵的逆
A_inv = np.linalg.inv(A)
print("矩阵A的逆:\n", A_inv)

# 特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues)
print("特征向量:\n", eigenvectors)

# 求解线性方程组 Ax = b
b = np.array([5, 11])
x = np.linalg.solve(A, b)
print("线性方程组解:", x)

第二部分:Pandas数据处理——从数据清洗到高级分析

DataFrame基础与数据读取

Pandas是基于NumPy构建的数据分析库,提供了DataFrame这一核心数据结构,非常适合处理表格数据。

import pandas as pd
import numpy as np

# 创建DataFrame
# 1. 从字典创建
data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 35, 28],
    '部门': ['技术部', '市场部', '技术部', '人事部'],
    '薪资': [8000, 12000, 15000, 9000],
    '入职日期': pd.date_range('2020-01-01', periods=4)
}
df = pd.DataFrame(data)
print("原始DataFrame:")
print(df)
print(f"\nDataFrame形状: {df.shape}")
print(f"数据类型:\n{df.dtypes}")

# 2. 从CSV/Excel读取
# df = pd.read_csv('data.csv', encoding='utf-8')
# df = pd.read_excel('data.xlsx', sheet_name='Sheet1')

# 3. 从SQL数据库读取
# import sqlite3
# conn = sqlite3.connect('database.db')
# df = pd.read_sql('SELECT * FROM table_name', conn)

# 查看数据基本信息
print("\n数据基本信息:")
print(df.info())
print("\n统计描述:")
print(df.describe())
print("\n前3行数据:")
print(df.head(3))
print("\n后2行数据:")
print(df.tail(2))

# 数据选择与索引
print("\n=== 数据选择 ===")
print("选择单列:")
print(df['姓名'])
print("\n选择多列:")
print(df[['姓名', '部门', '薪资']])
print("\n按位置选择:")
print(df.iloc[1:3, 1:3])  # 第1-2行,第1-2列
print("\n按标签选择:")
print(df.loc[1:2, ['姓名', '薪资']])  # 索引1-2,指定列
print("\n条件选择:")
print(df[df['薪资'] > 10000])  # 薪资大于10000的员工
print("\n多条件选择:")
print(df[(df['部门'] == '技术部') & (df['年龄'] < 30)])

数据清洗与预处理

数据清洗是数据分析中最耗时但最重要的步骤,通常占整个分析流程的60-80%时间。

# 创建包含问题的示例数据
data = {
    '姓名': ['张三', '李四', '王五', '赵六', '孙七', None, '周八'],
    '年龄': [25, 30, 35, 28, 40, 22, None],
    '部门': ['技术部', '市场部', '技术部', '人事部', '技术部', '市场部', '技术部'],
    '薪资': [8000, 12000, 15000, 9000, 18000, 8500, 20000],
    '邮箱': ['zhang3@company.com', 'li4@company.com', 'wang5@company.com', 
            'zhao6@company.com', 'sun7@company.com', None, 'zhou8@company.com'],
    '绩效': ['A', 'B', 'A', 'C', 'A', 'B', 'A']
}
df = pd.DataFrame(data)
print("原始数据(包含问题):")
print(df)

# 1. 处理缺失值
print("\n=== 缺失值处理 ===")
print("缺失值统计:")
print(df.isnull().sum())

# 删除缺失值
df_dropped = df.dropna()  # 删除任何包含NaN的行
print("\n删除缺失值后:")
print(df_dropped)

# 填充缺失值
df_filled = df.copy()
df_filled['姓名'] = df_filled['姓名'].fillna('未知')
df_filled['年龄'] = df_filled['年龄'].fillna(df_filled['年龄'].median())
df_filled['邮箱'] = df_filled['邮箱'].fillna('unknown@company.com')
print("\n填充缺失值后:")
print(df_filled)

# 2. 数据类型转换
print("\n=== 数据类型转换 ===")
df_clean = df_filled.copy()
df_clean['年龄'] = df_clean['年龄'].astype(int)  # 转换为整数
print("转换后数据类型:")
print(df_clean.dtypes)

# 3. 处理重复值
print("\n=== 重复值处理 ===")
df_dup = pd.DataFrame({
    '姓名': ['张三', '李四', '张三', '王五'],
    '年龄': [25, 30, 25, 35],
    '部门': ['技术部', '市场部', '技术部', '技术部']
})
print("包含重复值的数据:")
print(df_dup)
print("\n重复值数量:", df_dup.duplicated().sum())
print("\n删除重复值:")
print(df_dup.drop_duplicates())

# 4. 数据标准化与规范化
print("\n=== 数据标准化 ===")
# Z-score标准化
df_clean['薪资_zscore'] = (df_clean['薪资'] - df_clean['薪资'].mean()) / df_clean['薪资'].std()
# Min-Max归一化
df_clean['薪资_minmax'] = (df_clean['薪资'] - df_clean['薪资'].min()) / (df_clean['薪资'].max() - df_clean['薪资'].min())
print("标准化后的薪资:")
print(df_clean[['薪资', '薪资_zscore', '薪资_minmax']])

# 5. 异常值检测与处理
print("\n=== 异常值处理 ===")
# 使用IQR方法检测异常值
Q1 = df_clean['薪资'].quantile(0.25)
Q3 = df_clean['薪资'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

print(f"薪资正常范围: [{lower_bound:.2f}, {upper_bound:.2f}]")
outliers = df_clean[(df_clean['薪资'] < lower_bound) | (df_clean['薪资'] > upper_bound)]
print("异常值:")
print(outliers)

# 异常值处理:替换为边界值
df_clean['薪资_处理后'] = df_clean['薪资'].clip(lower=lower_bound, upper=upper_bound)
print("\n处理异常值后:")
print(df_clean[['薪资', '薪资_处理后']])

数据转换与高级操作

# 1. 数据分组与聚合
print("=== 数据分组与聚合 ===")
grouped = df_clean.groupby('部门')
print("按部门分组:")
for name, group in grouped:
    print(f"\n部门: {name}")
    print(group[['姓名', '薪资']])

# 聚合统计
agg_result = df_clean.groupby('部门').agg({
    '薪资': ['mean', 'max', 'min', 'count'],
    '年龄': 'mean'
})
print("\n聚合统计:")
print(agg_result)

# 2. 数据透视表
print("\n=== 数据透视表 ===")
pivot_df = pd.DataFrame({
    '日期': ['2023-01', '2023-01', '2023-02', '2023-02', '2023-03', '2023-03'],
    '产品': ['A', 'B', 'A', 'B', 'A', 'B'],
    '销售额': [100, 150, 120, 180, 110, 160],
    '利润': [20, 30, 25, 35, 22, 32]
})
pivot = pd.pivot_table(pivot_df, 
                       values=['销售额', '利润'], 
                       index='日期', 
                       columns='产品', 
                       aggfunc='sum')
print("透视表:")
print(pivot)

# 3. apply函数与自定义转换
print("\n=== apply函数 ===")
def categorize_age(age):
    if age < 30:
        return '青年'
    elif age < 40:
        return '中年'
    else:
        return '老年'

df_clean['年龄段'] = df_clean['年龄'].apply(categorize_age)
print("添加年龄段:")
print(df_clean[['姓名', '年龄', '年龄段']])

# 对多列应用函数
def salary_level(row):
    if row['薪资'] > 15000:
        return '高薪'
    elif row['薪资'] > 10000:
        return '中薪'
    else:
        return '低薪'

df_clean['薪资等级'] = df_clean.apply(salary_level, axis=1)
print("\n添加薪资等级:")
print(df_clean[['姓名', '薪资', '薪资等级']])

# 4. 合并与连接
print("\n=== 数据合并 ===")
df1 = pd.DataFrame({
    '员工ID': [1, 2, 3, 4],
    '姓名': ['张三', '李四', '王五', '赵六']
})
df2 = pd.DataFrame({
    '员工ID': [1, 2, 3, 5],
    '绩效': ['A', 'B', 'A', 'C']
})

# 合并(类似SQL的JOIN)
merged = pd.merge(df1, df2, on='员工ID', how='inner')
print("内连接:")
print(merged)

merged_left = pd.merge(df1, df2, on='员工ID', how='left')
print("\n左连接:")
print(merged_left)

# 5. 时间序列处理
print("\n=== 时间序列处理 ===")
date_df = pd.DataFrame({
    'date': pd.date_range('2023-01-01', periods=10, freq='D'),
    'value': np.random.randint(100, 200, 10)
})
date_df['year'] = date_df['date'].dt.year
date_df['month'] = date_df['date'].dt.month
date_df['dayofweek'] = date_df['date'].dt.dayofweek
date_df['is_weekend'] = date_df['dayofweek'].isin([5, 6])
print("时间特征提取:")
print(date_df)

实战案例:销售数据分析

# 生成模拟销售数据
np.random.seed(42)
dates = pd.date_range('2023-01-01', '2023-12-31', freq='D')
products = ['笔记本电脑', '显示器', '键盘', '鼠标', '耳机']
regions = ['华北', '华东', '华南', '西南']

sales_data = []
for date in dates:
    for _ in range(5):  # 每天5条记录
        product = np.random.choice(products)
        region = np.random.choice(regions)
        quantity = np.random.randint(1, 10)
        unit_price = np.random.randint(50, 500)
        sales_data.append({
            '日期': date,
            '产品': product,
            '区域': region,
            '数量': quantity,
            '单价': unit_price,
            '销售额': quantity * unit_price
        })

sales_df = pd.DataFrame(sales_data)
print("销售数据前5行:")
print(sales_df.head())

# 1. 基础统计分析
print("\n=== 基础统计 ===")
print(f"总销售额: {sales_df['销售额'].sum():,.2f}")
print(f"平均日销售额: {sales_df.groupby('日期')['销售额'].sum().mean():,.2f}")
print("\n按产品统计:")
product_stats = sales_df.groupby('产品').agg({
    '销售额': ['sum', 'mean', 'count'],
    '数量': 'sum'
}).round(2)
print(product_stats)

# 2. 时间趋势分析
print("\n=== 时间趋势 ===")
monthly_sales = sales_df.groupby(sales_df['日期'].dt.to_period('M'))['销售额'].sum()
print("月度销售额:")
print(monthly_sales)

# 3. 区域分析
print("\n=== 区域分析 ===")
region_analysis = sales_df.groupby(['区域', '产品'])['销售额'].sum().unstack()
print("各区域产品销售额:")
print(region_analysis)

# 4. 畅销产品分析
print("\n=== 畅销产品分析 ===")
top_products = sales_df.groupby('产品')['销售额'].sum().sort_values(ascending=False)
print("产品销售额排名:")
print(top_products)

# 5. 数据透视表分析
print("\n=== 数据透视表分析 ===")
pivot_sales = pd.pivot_table(sales_df, 
                             values='销售额', 
                             index='区域', 
                             columns='产品', 
                             aggfunc='sum',
                             margins=True,
                             margins_name='总计')
print("区域-产品销售透视表:")
print(pivot_sales)

第三部分:数据可视化——让数据说话

Matplotlib基础绘图

Matplotlib是Python最基础的绘图库,虽然语法相对繁琐,但功能强大且灵活。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 设置中文字体(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号

# 1. 折线图
plt.figure(figsize=(10, 6))
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y1, label='sin(x)', color='blue', linewidth=2, linestyle='-')
plt.plot(x, y2, label='cos(x)', color='red', linewidth=2, linestyle='--')
plt.title('正弦和余弦函数', fontsize=16)
plt.xlabel('X轴', fontsize=12)
plt.ylabel('Y轴', fontsize=12)
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

# 2. 散点图
plt.figure(figsize=(8, 6))
np.random.seed(42)
x = np.random.normal(0, 1, 100)
y = 2 * x + np.random.normal(0, 0.5, 100)

plt.scatter(x, y, c='purple', alpha=0.6, s=50)
plt.title('散点图示例', fontsize=16)
plt.xlabel('X变量', fontsize=12)
plt.ylabel('Y变量', fontsize=12)
plt.show()

# 3. 柱状图
plt.figure(figsize=(10, 6))
categories = ['产品A', '产品B', '产品C', '产品D', '产品E']
values = [25, 40, 30, 35, 28]

plt.bar(categories, values, color=['#FF9999', '#66B2FF', '#99FF99', '#FFCC99', '#CC99FF'])
plt.title('产品销量对比', fontsize=16)
plt.xlabel('产品', fontsize=12)
plt.ylabel('销量', fontsize=12)
plt.xticks(rotation=45)
plt.show()

# 4. 直方图
plt.figure(figsize=(10, 6))
data = np.random.randn(1000)

plt.hist(data, bins=30, color='skyblue', edgecolor='black', alpha=0.7)
plt.title('正态分布直方图', fontsize=16)
plt.xlabel('数值', fontsize=12)
plt.ylabel('频数', fontsize=12)
plt.show()

# 5. 饼图
plt.figure(figsize=(8, 8))
sizes = [30, 25, 15, 20, 10]
labels = ['产品A', '产品B', '产品C', '产品D', '产品E']
colors = ['#FF9999', '#66B2FF', '#99FF99', '#FFCC99', '#CC99FF']

plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
plt.title('市场份额分布', fontsize=16)
plt.show()

# 6. 子图(多图合一)
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# 折线图
axes[0, 0].plot(x, y1, color='blue')
axes[0, 0].set_title('折线图')

# 散点图
axes[0, 1].scatter(x, y, color='red', alpha=0.6)
axes[0, 1].set_title('散点图')

# 柱状图
axes[1, 0].bar(categories, values, color='green')
axes[1, 0].set_title('柱状图')
axes[1, 0].tick_params(axis='x', rotation=45)

# 直方图
axes[1, 1].hist(data, bins=20, color='purple', alpha=0.7)
axes[1, 1].set_title('直方图')

plt.tight_layout()
plt.show()

Seaborn高级可视化

Seaborn是基于Matplotlib的高级绘图库,提供了更美观的默认样式和更简单的API。

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 设置Seaborn样式
sns.set_style("whitegrid")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 创建示例数据
np.random.seed(42)
data = pd.DataFrame({
    '类别': np.random.choice(['A', 'B', 'C'], 200),
    '数值1': np.random.normal(0, 1, 200),
    '数值2': np.random.normal(2, 1.5, 200),
    '分组': np.random.choice(['X', 'Y'], 200)
})

# 1. 分布图
plt.figure(figsize=(12, 4))

plt.subplot(1, 3, 1)
sns.histplot(data=data, x='数值1', kde=True, color='blue')
plt.title('直方图+密度曲线')

plt.subplot(1, 3, 2)
sns.boxplot(data=data, x='类别', y='数值1', palette='Set2')
plt.title('箱线图')

plt.subplot(1, 3, 3)
sns.violinplot(data=data, x='类别', y='数值1', palette='Set3')
plt.title('小提琴图')

plt.tight_layout()
plt.show()

# 2. 关系图
plt.figure(figsize=(12, 4))

plt.subplot(1, 3, 1)
sns.scatterplot(data=data, x='数值1', y='数值2', hue='类别', style='分组', s=60)
plt.title('散点图')

plt.subplot(1, 3, 2)
sns.lineplot(data=data, x='数值1', y='数值2', hue='类别')
plt.title('线图')

plt.subplot(1, 3, 3)
sns.regplot(data=data, x='数值1', y='数值2', scatter_kws={'alpha':0.5})
plt.title('回归图')

plt.tight_layout()
plt.show()

# 3. 分类图
plt.figure(figsize=(12, 4))

plt.subplot(1, 3, 1)
sns.barplot(data=data, x='类别', y='数值1', hue='分组', ci=None)
plt.title('条形图')

plt.subplot(1, 3, 2)
sns.countplot(data=data, x='类别', hue='分组', palette='viridis')
plt.title('计数图')

plt.subplot(1, 3, 3)
sns.pointplot(data=data, x='类别', y='数值1', hue='分组', ci=None)
plt.title('点图')

plt.tight_layout()
plt.show()

# 4. 矩阵图
plt.figure(figsize=(10, 6))
corr_matrix = data[['数值1', '数值2']].corr()
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0)
plt.title('相关性热力图')
plt.show()

# 5. 配对图
sns.pairplot(data, hue='类别', vars=['数值1', '数值2'], palette='husl')
plt.suptitle('配对图', y=1.02)
plt.show()

# 6. 分布矩阵
sns.jointplot(data=data, x='数值1', y='数值2', kind='scatter', height=6)
plt.suptitle('联合分布图', y=1.02)
plt.show()

实战案例:销售数据可视化分析

# 继续使用之前的销售数据
sales_df = pd.DataFrame(sales_data)

# 1. 月度销售趋势
plt.figure(figsize=(12, 6))
monthly_sales = sales_df.groupby(sales_df['日期'].dt.to_period('M'))['销售额'].sum()
monthly_sales.index = monthly_sales.index.astype(str)

plt.plot(monthly_sales.index, monthly_sales.values, marker='o', linewidth=2, markersize=8)
plt.title('2023年月度销售趋势', fontsize=16)
plt.xlabel('月份', fontsize=12)
plt.ylabel('销售额', fontsize=12)
plt.xticks(rotation=45)
plt.grid(True, alpha=0.3)
plt.show()

# 2. 产品销售对比
plt.figure(figsize=(12, 6))
product_sales = sales_df.groupby('产品')['销售额'].sum().sort_values(ascending=False)

sns.barplot(x=product_sales.index, y=product_sales.values, palette='viridis')
plt.title('各产品销售额对比', fontsize=16)
plt.xlabel('产品', fontsize=12)
plt.ylabel('销售额', fontsize=12)
plt.xticks(rotation=45)
plt.show()

# 3. 区域销售分布
plt.figure(figsize=(10, 8))
region_sales = sales_df.groupby('区域')['销售额'].sum()

plt.pie(region_sales.values, labels=region_sales.index, autopct='%1.1f%%', 
        colors=sns.color_palette('pastel'))
plt.title('各区域销售额占比', fontsize=16)
plt.show()

# 4. 产品-区域热力图
plt.figure(figsize=(10, 6))
pivot_data = sales_df.groupby(['产品', '区域'])['销售额'].sum().unstack()
sns.heatmap(pivot_data, annot=True, fmt='.0f', cmap='YlOrRd', linewidths=0.5)
plt.title('产品-区域销售额热力图', fontsize=16)
plt.xlabel('区域', fontsize=12)
plt.ylabel('产品', fontsize=12)
plt.show()

# 5. 销售分布直方图
plt.figure(figsize=(10, 6))
sns.histplot(data=sales_df, x='销售额', bins=50, kde=True, color='steelblue')
plt.title('销售额分布', fontsize=16)
plt.xlabel('单笔销售额', fontsize=12)
plt.ylabel('频数', fontsize=12)
plt.show()

# 6. 散点矩阵(多变量关系)
plt.figure(figsize=(10, 8))
sns.pairplot(sales_df[['数量', '单价', '销售额', '产品']], 
             hue='产品', 
             palette='husl',
             diag_kind='kde')
plt.suptitle('销售数据多变量关系', y=1.02)
plt.show()

第四部分:综合实战——解决真实数据分析难题

案例:电商用户行为分析

# 生成模拟电商用户行为数据
np.random.seed(42)
n_users = 1000
n_products = 50

# 用户基础信息
user_data = {
    'user_id': range(1, n_users + 1),
    'age': np.random.randint(18, 65, n_users),
    'gender': np.random.choice(['男', '女'], n_users, p=[0.48, 0.52]),
    'city': np.random.choice(['北京', '上海', '广州', '深圳', '杭州'], n_users),
    'register_date': pd.date_range('2022-01-01', periods=n_users, freq='D')
}

# 商品信息
product_data = {
    'product_id': range(1, n_products + 1),
    'category': np.random.choice(['电子产品', '服装', '食品', '家居', '美妆'], n_products),
    'price': np.random.randint(50, 1000, n_products)
}

# 用户行为数据(浏览、加购、购买)
behavior_records = []
for _ in range(5000):
    user_id = np.random.randint(1, n_users + 1)
    product_id = np.random.randint(1, n_products + 1)
    behavior = np.random.choice(['浏览', '加购', '购买'], p=[0.6, 0.25, 0.15])
    
    # 购买行为有金额
    if behavior == '购买':
        amount = product_data['price'][product_id - 1] * np.random.uniform(0.9, 1.1)
    else:
        amount = 0
    
    behavior_records.append({
        'user_id': user_id,
        'product_id': product_id,
        'behavior': behavior,
        'amount': amount,
        'timestamp': pd.Timestamp.now() - pd.Timedelta(days=np.random.randint(0, 365))
    })

users = pd.DataFrame(user_data)
products = pd.DataFrame(product_data)
behaviors = pd.DataFrame(behavior_records)

print("=== 电商用户行为分析 ===")
print("\n用户数据:")
print(users.head())
print("\n商品数据:")
print(products.head())
print("\n行为数据:")
print(behaviors.head())

# 1. 用户基础分析
print("\n=== 用户基础分析 ===")
print(f"总用户数: {len(users)}")
print(f"用户年龄分布:\n{users['age'].describe()}")
print("\n性别分布:")
print(users['gender'].value_counts(normalize=True))
print("\n城市分布:")
print(users['city'].value_counts())

# 2. 行为分析
print("\n=== 行为分析 ===")
print("行为类型分布:")
behavior_counts = behaviors['behavior'].value_counts()
print(behavior_counts)

# 转化率分析
total_users = behaviors['user_id'].nunique()
browsed_users = behaviors[behaviors['behavior'] == '浏览']['user_id'].nunique()
purchased_users = behaviors[behaviors['behavior'] == '购买']['user_id'].nunique()
conversion_rate = purchased_users / browsed_users * 100

print(f"\n浏览用户数: {browsed_users}")
print(f"购买用户数: {purchased_users}")
print(f"转化率: {conversion_rate:.2f}%")

# 3. 销售分析
print("\n=== 销售分析 ===")
purchase_data = behaviors[behaviors['behavior'] == '购买']
print(f"总销售额: {purchase_data['amount'].sum():,.2f}")
print(f"平均订单金额: {purchase_data['amount'].mean():,.2f}")
print(f"订单数量: {len(purchase_data)}")

# 4. 用户价值分析(RFM模型简化版)
print("\n=== 用户价值分析 ===")
user_purchase = purchase_data.groupby('user_id').agg({
    'amount': ['sum', 'count'],
    'timestamp': 'max'
}).reset_index()
user_purchase.columns = ['user_id', '总消费', '购买次数', '最近购买']

# 计算R(最近购买天数)
current_date = pd.Timestamp.now()
user_purchase['R'] = (current_date - user_purchase['最近购买']).dt.days

# 分层
def user_segment(row):
    if row['总消费'] > user_purchase['总消费'].quantile(0.8) and row['R'] < 30:
        return '高价值'
    elif row['总消费'] > user_purchase['总消费'].quantile(0.5) and row['R'] < 60:
        return '中价值'
    else:
        return '低价值'

user_purchase['价值等级'] = user_purchase.apply(user_segment, axis=1)
print("用户价值分布:")
print(user_purchase['价值等级'].value_counts())

# 5. 商品分析
print("\n=== 商品分析 ===")
product_sales = purchase_data.groupby('product_id').agg({
    'amount': 'sum',
    'user_id': 'count'
}).reset_index()
product_sales.columns = ['product_id', '销售额', '购买次数']
product_sales = product_sales.merge(products, on='product_id')
print("畅销商品TOP10:")
print(product_sales.sort_values('销售额', ascending=False).head(10))

# 6. 类别分析
print("\n=== 类别分析 ===")
category_sales = product_sales.groupby('category')['销售额'].sum().sort_values(ascending=False)
print("各类别销售额:")
print(category_sales)

可视化分析

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 1. 用户年龄分布
plt.figure(figsize=(10, 6))
sns.histplot(data=users, x='age', bins=20, kde=True, color='steelblue')
plt.title('用户年龄分布', fontsize=16)
plt.xlabel('年龄', fontsize=12)
plt.ylabel('人数', fontsize=12)
plt.show()

# 2. 行为转化漏斗
plt.figure(figsize=(8, 6))
behavior_counts = behaviors['behavior'].value_counts()
sns.barplot(x=behavior_counts.index, y=behavior_counts.values, palette='viridis')
plt.title('用户行为分布', fontsize=16)
plt.xlabel('行为类型', fontsize=12)
plt.ylabel('次数', fontsize=12)
plt.show()

# 3. 销售趋势
plt.figure(figsize=(12, 6))
daily_sales = purchase_data.groupby(purchase_data['timestamp'].dt.date)['amount'].sum()
plt.plot(daily_sales.index, daily_sales.values, linewidth=1.5, alpha=0.8)
plt.title('日销售额趋势', fontsize=16)
plt.xlabel('日期', fontsize=12)
plt.ylabel('销售额', fontsize=12)
plt.xticks(rotation=45)
plt.show()

# 4. 用户价值分布
plt.figure(figsize=(8, 6))
value_counts = user_purchase['价值等级'].value_counts()
plt.pie(value_counts.values, labels=value_counts.index, autopct='%1.1f%%', 
        colors=sns.color_palette('pastel'))
plt.title('用户价值分布', fontsize=16)
plt.show()

# 5. 商品类别销售占比
plt.figure(figsize=(8, 8))
plt.pie(category_sales.values, labels=category_sales.index, autopct='%1.1f%%', 
        colors=sns.color_palette('Set3'))
plt.title('商品类别销售占比', fontsize=16)
plt.show()

# 6. 相关性分析
plt.figure(figsize=(8, 6))
# 合并用户和购买数据
user_purchase_full = user_purchase.merge(users, on='user_id')
correlation_data = user_purchase_full[['总消费', '购买次数', 'R', 'age']].corr()
sns.heatmap(correlation_data, annot=True, cmap='coolwarm', center=0, fmt='.2f')
plt.title('用户特征相关性', fontsize=16)
plt.show()

第五部分:性能优化与最佳实践

1. 内存优化技巧

import pandas as pd
import numpy as np

# 1. 优化数据类型
def optimize_memory(df):
    """优化DataFrame内存使用"""
    df_optimized = df.copy()
    
    for col in df_optimized.columns:
        col_type = df_optimized[col].dtype
        
        if col_type != object:
            c_min = df_optimized[col].min()
            c_max = df_optimized[col].max()
            
            if str(col_type)[:3] == 'int':
                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                    df_optimized[col] = df_optimized[col].astype(np.int8)
                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                    df_optimized[col] = df_optimized[col].astype(np.int16)
                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                    df_optimized[col] = df_optimized[col].astype(np.int32)
            else:
                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                    df_optimized[col] = df_optimized[col].astype(np.float16)
                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                    df_optimized[col] = df_optimized[col].astype(np.float32)
    
    return df_optimized

# 示例
large_df = pd.DataFrame({
    'id': range(100000),
    'value1': np.random.randint(0, 100, 100000),
    'value2': np.random.randint(0, 1000, 100000),
    'score': np.random.random(100000)
})

print("优化前内存使用:")
print(large_df.info(memory_usage='deep'))

optimized_df = optimize_memory(large_df)
print("\n优化后内存使用:")
print(optimized_df.info(memory_usage='deep'))

2. 向量化操作优化

# 避免使用循环,使用向量化操作
import time

# 创建大型数据集
n = 1000000
df = pd.DataFrame({
    'a': np.random.random(n),
    'b': np.random.random(n)
})

# 方法1:循环(慢)
def calc_loop(df):
    result = []
    for i in range(len(df)):
        if df.loc[i, 'a'] > 0.5:
            result.append(df.loc[i, 'a'] + df.loc[i, 'b'])
        else:
            result.append(df.loc[i, 'a'] - df.loc[i, 'b'])
    return result

# 方法2:向量化(快)
def calc_vectorized(df):
    return np.where(df['a'] > 0.5, df['a'] + df['b'], df['a'] - df['b'])

# 方法3:使用apply(中等)
def calc_apply(df):
    return df.apply(lambda row: row['a'] + row['b'] if row['a'] > 0.5 else row['a'] - row['b'], axis=1)

# 性能对比
start = time.time()
result1 = calc_loop(df)
time1 = time.time() - start

start = time.time()
result2 = calc_vectorized(df)
time2 = time.time() - start

start = time.time()
result3 = calc_apply(df)
time3 = time.time() - start

print(f"循环方式耗时: {time1:.4f}秒")
print(f"向量化方式耗时: {time2:.4f}秒")
print(f"apply方式耗时: {time3:.4f}秒")
print(f"向量化比循环快: {time1/time2:.1f}倍")

3. 大数据处理技巧

# 处理大数据集时使用chunksize
def process_large_csv(file_path):
    """分块读取处理大文件"""
    chunks = pd.read_csv(file_path, chunksize=10000)
    results = []
    
    for chunk in chunks:
        # 对每个块进行处理
        chunk_result = chunk.groupby('category')['sales'].sum()
        results.append(chunk_result)
    
    # 合并结果
    final_result = pd.concat(results).groupby(level=0).sum()
    return final_result

# 使用query方法进行高效筛选
def efficient_filter(df):
    """使用query进行高效筛选"""
    # 慢:df[(df['a'] > 0.5) & (df['b'] < 0.8) & (df['c'] == 'value')]
    # 快:
    return df.query('a > 0.5 and b < 0.8 and c == "value"')

# 使用eval进行高效计算
def efficient_calc(df):
    """使用eval进行高效计算"""
    # 慢:df['result'] = df['a'] * df['b'] + df['c'] - df['d']
    # 快:
    df.eval('result = a * b + c - d', inplace=True)
    return df

4. 代码组织与模块化

# 推荐的数据分析项目结构
"""
project/
├── data/
│   ├── raw/          # 原始数据
│   └── processed/    # 处理后数据
├── src/
│   ├── __init__.py
│   ├── data_loader.py    # 数据加载
│   ├── data_cleaner.py   # 数据清洗
│   ├── analyzer.py       # 分析函数
│   └── visualizer.py     # 可视化函数
├── notebooks/
│   └── analysis.ipynb    # 分析笔记本
├── requirements.txt
└── README.md
"""

# 示例:创建一个分析模块
# src/analyzer.py
class SalesAnalyzer:
    """销售数据分析器"""
    
    def __init__(self, data):
        self.data = data
    
    def get_monthly_sales(self):
        """获取月度销售额"""
        return self.data.groupby(
            self.data['日期'].dt.to_period('M')
        )['销售额'].sum()
    
    def get_top_products(self, n=10):
        """获取畅销商品"""
        return self.data.groupby('产品')['销售额'].sum().nlargest(n)
    
    def get_conversion_rate(self):
        """计算转化率"""
        total = self.data['user_id'].nunique()
        buyers = self.data[self.data['behavior'] == '购买']['user_id'].nunique()
        return buyers / total * 100

# 使用示例
# from src.analyzer import SalesAnalyzer
# analyzer = SalesAnalyzer(sales_df)
# monthly = analyzer.get_monthly_sales()

第六部分:职场应用与职业发展建议

1. 常见职场场景解决方案

场景1:快速生成周报

def generate_weekly_report(df, week_start):
    """快速生成周报"""
    week_end = week_start + pd.Timedelta(days=6)
    week_data = df[(df['日期'] >= week_start) & (df['日期'] <= week_end)]
    
    report = {
        '周期': f"{week_start} 至 {week_end}",
        '总销售额': week_data['销售额'].sum(),
        '订单数': len(week_data),
        '平均客单价': week_data['销售额'].sum() / len(week_data),
        '热销产品': week_data.groupby('产品')['销售额'].sum().nlargest(3).index.tolist()
    }
    return report

场景2:异常数据自动检测

def detect_anomalies(df, column, threshold=3):
    """使用Z-score检测异常值"""
    z_scores = np.abs((df[column] - df[column].mean()) / df[column].std())
    anomalies = df[z_scores > threshold]
    return anomalies

场景3:A/B测试分析

def ab_test_analysis(control, treatment):
    """A/B测试分析"""
    from scipy import stats
    
    # 计算统计显著性
    t_stat, p_value = stats.ttest_ind(control, treatment)
    
    result = {
        '控制组均值': control.mean(),
        '实验组均值': treatment.mean(),
        '提升百分比': (treatment.mean() - control.mean()) / control.mean() * 100,
        'p值': p_value,
        '显著': p_value < 0.05
    }
    return result

2. 提升职场竞争力的建议

  1. 建立个人作品集

    • 在GitHub上创建数据分析项目
    • 撰写技术博客分享解决方案
    • 参与Kaggle竞赛
  2. 持续学习

    • 关注Python数据分析领域的最新发展
    • 学习机器学习、深度学习等进阶技能
    • 掌握SQL、Spark等大数据工具
  3. 提升业务理解

    • 理解所在行业的业务逻辑
    • 学会用数据驱动业务决策
    • 培养数据讲故事的能力
  4. 软技能提升

    • 提高沟通能力,能向非技术人员解释分析结果
    • 学会项目管理,高效推进数据分析项目
    • 培养商业敏感度,发现数据背后的商业机会

3. 简历与面试准备

简历中应该突出的技能点:

  • 熟练使用Python进行数据清洗、分析和可视化
  • 掌握pandas、numpy、matplotlib/seaborn等核心库
  • 具备实际项目经验,能独立完成数据分析全流程
  • 熟悉统计学基础和机器学习算法

面试常见问题准备:

  • 如何处理缺失值和异常值?
  • 如何优化pandas代码性能?
  • 如何设计一个数据分析项目?
  • 如何向业务部门解释分析结果?

总结

通过本课程的学习,你已经系统掌握了Python数据分析的核心技能:

  1. NumPy:高效数值计算的基础,向量化操作提升性能
  2. Pandas:强大的数据处理能力,从清洗到高级分析
  3. 可视化:用图表让数据说话,提升报告说服力
  4. 实战应用:解决真实业务问题,创造商业价值
  5. 性能优化:处理大数据,提升工作效率
  6. 职场应用:将技能转化为职业竞争力

记住,数据分析不仅仅是写代码,更重要的是:

  • 理解业务:数据背后的故事
  • 解决问题:用数据驱动决策
  • 持续学习:技术日新月异,保持好奇心
  • 沟通表达:让非技术人员理解你的发现

现在,你已经具备了从入门到精通的完整知识体系。接下来就是不断实践,在真实项目中磨练技能,最终成为数据分析领域的专家!

下一步行动建议:

  1. 找一个你感兴趣的数据集进行实战练习
  2. 在工作中寻找可以自动化的数据分析任务
  3. 参与开源项目或Kaggle竞赛
  4. 持续学习新的库和工具(如Polars、Dask等)
  5. 建立个人品牌,分享你的数据分析成果

祝你在数据分析的道路上越走越远,职场竞争力不断提升!