引言

在当今数据驱动的时代,数据分析已成为各行各业不可或缺的技能。Python作为数据分析的主要编程语言,其生态系统中的pandas库更是数据分析的核心工具。pandas提供了高性能、易于使用的数据结构和数据分析工具,使得数据清洗、转换、分析和可视化变得简单高效。本文将全面解析pandas库在数据分析全流程中的应用,从基础概念到实战技巧,帮助读者掌握这一必备技能。

pandas基础

pandas简介

pandas是基于NumPy的一种工具,该工具是为了解决数据分析任务而创建的。它纳入了大量库和一些标准的数据模型,提供了高效操作大型数据集所需的工具。pandas主要有两种数据结构:Series(一维数组)和DataFrame(二维表格型数据结构)。

安装与导入

在开始使用pandas之前,需要确保已安装该库。可以通过pip进行安装:

pip install pandas 

安装完成后,在Python脚本或Jupyter notebook中导入pandas:

import pandas as pd import numpy as np 

核心数据结构

Series

Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。

# 创建Series s = pd.Series([1, 3, 5, np.nan, 6, 8]) print(s) 

输出:

0 1.0 1 3.0 2 5.0 3 NaN 4 6.0 5 8.0 dtype: float64 

DataFrame

DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。

# 创建DataFrame data = {'name': ['Alice', 'Bob', 'Charlie', 'David'], 'age': [25, 30, 35, 40], 'city': ['New York', 'Los Angeles', 'Chicago', 'Houston']} df = pd.DataFrame(data) print(df) 

输出:

 name age city 0 Alice 25 New York 1 Bob 30 Los Angeles 2 Charlie 35 Chicago 3 David 40 Houston 

基本操作

查看数据

# 查看前几行数据 print(df.head(2)) # 查看后几行数据 print(df.tail(2)) # 查看数据的基本信息 print(df.info()) # 查看数据的统计摘要 print(df.describe()) 

选择数据

# 选择单列 print(df['name']) # 选择多列 print(df[['name', 'age']]) # 使用loc选择行和列 print(df.loc[0:2, ['name', 'city']]) # 使用iloc选择行和列(基于位置) print(df.iloc[0:2, 0:2]) 

数据过滤

# 条件过滤 print(df[df['age'] > 30]) # 多条件过滤 print(df[(df['age'] > 25) & (df['city'] == 'New York')]) 

数据清洗

数据清洗是数据分析过程中至关重要的一步,原始数据往往存在各种问题,如缺失值、异常值、重复值等。pandas提供了丰富的工具来处理这些问题。

处理缺失值

检测缺失值

# 创建包含缺失值的DataFrame data = {'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'], 'age': [25, 30, np.nan, 40, 25], 'salary': [50000, 60000, 70000, np.nan, 55000], 'department': ['HR', 'IT', 'Finance', 'IT', np.nan]} df_missing = pd.DataFrame(data) # 检测缺失值 print(df_missing.isnull()) # 统计每列的缺失值数量 print(df_missing.isnull().sum()) 

删除缺失值

# 删除包含缺失值的行 df_dropna = df_missing.dropna() print(df_dropna) # 删除全部为缺失值的行(如果有) df_dropna_all = df_missing.dropna(how='all') print(df_dropna_all) # 删除指定列中包含缺失值的行 df_dropna_col = df_missing.dropna(subset=['age']) print(df_dropna_col) 

填充缺失值

# 用固定值填充 df_fill_value = df_missing.fillna(0) print(df_fill_value) # 用均值填充数值列 df_fill_mean = df_missing.copy() df_fill_mean['age'] = df_fill_mean['age'].fillna(df_fill_mean['age'].mean()) df_fill_mean['salary'] = df_fill_mean['salary'].fillna(df_fill_mean['salary'].mean()) print(df_fill_mean) # 用前一个值填充(向前填充) df_fill_ffill = df_missing.fillna(method='ffill') print(df_fill_ffill) # 用后一个值填充(向后填充) df_fill_bfill = df_missing.fillna(method='bfill') print(df_fill_bfill) # 使用插值法填充 df_fill_interpolate = df_missing.copy() df_fill_interpolate['age'] = df_fill_interpolate['age'].interpolate() print(df_fill_interpolate) 

处理重复值

检测重复值

# 创建包含重复值的DataFrame data = {'name': ['Alice', 'Bob', 'Alice', 'David', 'Bob'], 'age': [25, 30, 25, 40, 30], 'city': ['New York', 'Los Angeles', 'New York', 'Houston', 'Los Angeles']} df_duplicates = pd.DataFrame(data) # 检测重复行 print(df_duplicates.duplicated()) # 统计重复行数量 print(df_duplicates.duplicated().sum()) 

删除重复值

# 删除完全重复的行 df_drop_duplicates = df_duplicates.drop_duplicates() print(df_drop_duplicates) # 基于特定列删除重复值 df_drop_subset = df_duplicates.drop_duplicates(subset=['name']) print(df_drop_subset) # 保留最后一个重复值 df_keep_last = df_duplicates.drop_duplicates(keep='last') print(df_keep_last) 

处理异常值

异常值是数据集中明显偏离其他观测值的值。处理异常值的方法有多种,取决于异常值的性质和分析的目的。

检测异常值

# 创建包含异常值的DataFrame np.random.seed(42) data = {'value': np.concatenate([np.random.normal(0, 1, 50), [10, -10]])} df_outliers = pd.DataFrame(data) # 使用箱线图检测异常值 import matplotlib.pyplot as plt df_outliers.boxplot(column=['value']) plt.show() # 使用Z-score检测异常值 from scipy import stats z_scores = np.abs(stats.zscore(df_outliers['value'])) threshold = 3 outliers = np.where(z_scores > threshold) print("异常值的索引:", outliers[0]) # 使用IQR(四分位距)检测异常值 Q1 = df_outliers['value'].quantile(0.25) Q3 = df_outliers['value'].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR outliers_iqr = df_outliers[(df_outliers['value'] < lower_bound) | (df_outliers['value'] > upper_bound)] print("异常值:n", outliers_iqr) 

处理异常值

# 删除异常值 df_remove_outliers = df_outliers[(df_outliers['value'] >= lower_bound) & (df_outliers['value'] <= upper_bound)] print("删除异常值后的数据:n", df_remove_outliers) # 替换异常值为边界值 df_replace_outliers = df_outliers.copy() df_replace_outliers.loc[df_outliers['value'] < lower_bound, 'value'] = lower_bound df_replace_outliers.loc[df_outliers['value'] > upper_bound, 'value'] = upper_bound print("替换异常值为边界值后的数据:n", df_replace_outliers) # 替换异常值为中位数 median_value = df_outliers['value'].median() df_replace_median = df_outliers.copy() df_replace_median.loc[df_outliers['value'] < lower_bound, 'value'] = median_value df_replace_median.loc[df_outliers['value'] > upper_bound, 'value'] = median_value print("替换异常值为中位数后的数据:n", df_replace_median) 

数据类型转换

在数据分析过程中,经常需要将数据从一种类型转换为另一种类型,以便进行正确的计算和分析。

# 创建包含不同数据类型的DataFrame data = {'name': ['Alice', 'Bob', 'Charlie'], 'age': ['25', '30', '35'], 'salary': ['50000', '60000', '70000'], 'join_date': ['2020-01-15', '2019-05-20', '2018-11-10']} df_types = pd.DataFrame(data) # 查看数据类型 print("原始数据类型:n", df_types.dtypes) # 将字符串转换为数值类型 df_types['age'] = df_types['age'].astype(int) df_types['salary'] = df_types['salary'].astype(float) print("转换后的数据类型:n", df_types.dtypes) # 将字符串转换为日期类型 df_types['join_date'] = pd.to_datetime(df_types['join_date']) print("转换日期后的数据类型:n", df_types.dtypes) # 使用to_numeric处理包含非数值的列 data = {'value': ['100', '200', '300', '400', 'abc']} df_mixed = pd.DataFrame(data) print("混合数据类型:n", df_mixed.dtypes) # 转换时忽略错误 df_mixed['value'] = pd.to_numeric(df_mixed['value'], errors='coerce') print("转换后的数据:n", df_mixed) print("转换后的数据类型:n", df_mixed.dtypes) 

数据转换与预处理

数据清洗完成后,通常需要进行一系列转换和预处理操作,以便更好地进行数据分析。

数据标准化与归一化

标准化和归一化是常用的数据预处理技术,用于将不同尺度的特征转换到相似的范围内。

# 创建示例数据 np.random.seed(42) data = { 'feature1': np.random.normal(100, 20, 100), 'feature2': np.random.normal(5, 1, 100), 'feature3': np.random.normal(1000, 200, 100) } df_scale = pd.DataFrame(data) # Z-score标准化(均值为0,标准差为1) from sklearn.preprocessing import StandardScaler scaler = StandardScaler() df_standardized = pd.DataFrame(scaler.fit_transform(df_scale), columns=df_scale.columns) print("标准化后的数据统计描述:n", df_standardized.describe()) # Min-Max归一化(将数据缩放到[0,1]区间) from sklearn.preprocessing import MinMaxScaler min_max_scaler = MinMaxScaler() df_normalized = pd.DataFrame(min_max_scaler.fit_transform(df_scale), columns=df_scale.columns) print("归一化后的数据统计描述:n", df_normalized.describe()) # 手动实现标准化 df_manual_standardized = (df_scale - df_scale.mean()) / df_scale.std() print("手动标准化后的数据统计描述:n", df_manual_standardized.describe()) # 手动实现归一化 df_manual_normalized = (df_scale - df_scale.min()) / (df_scale.max() - df_scale.min()) print("手动归一化后的数据统计描述:n", df_manual_normalized.describe()) 

特征编码

在处理分类变量时,通常需要将其转换为数值形式,以便进行机器学习建模。

# 创建包含分类变量的DataFrame data = { 'color': ['red', 'blue', 'green', 'red', 'blue', 'green'], 'size': ['S', 'M', 'L', 'S', 'M', 'L'], 'price': [10, 20, 30, 15, 25, 35] } df_categorical = pd.DataFrame(data) # 标签编码(适用于有序分类变量) from sklearn.preprocessing import LabelEncoder le = LabelEncoder() df_categorical['size_encoded'] = le.fit_transform(df_categorical['size']) print("标签编码后的数据:n", df_categorical) # 独热编码(适用于无序分类变量) df_one_hot = pd.get_dummies(df_categorical, columns=['color'], prefix=['color']) print("独热编码后的数据:n", df_one_hot) # 使用sklearn的OneHotEncoder from sklearn.preprocessing import OneHotEncoder ohe = OneHotEncoder(sparse=False) color_encoded = ohe.fit_transform(df_categorical[['color']]) df_ohe = pd.DataFrame(color_encoded, columns=ohe.get_feature_names(['color'])) df_ohe = pd.concat([df_categorical, df_ohe], axis=1) print("使用sklearn独热编码后的数据:n", df_ohe) 

特征工程

特征工程是创建新特征或转换现有特征以提高模型性能的过程。

# 创建示例数据 np.random.seed(42) dates = pd.date_range(start='2020-01-01', end='2020-12-31') sales = np.random.randint(100, 1000, size=len(dates)) df_feature = pd.DataFrame({'date': dates, 'sales': sales}) # 从日期中提取特征 df_feature['year'] = df_feature['date'].dt.year df_feature['month'] = df_feature['date'].dt.month df_feature['day'] = df_feature['date'].dt.day df_feature['dayofweek'] = df_feature['date'].dt.dayofweek df_feature['quarter'] = df_feature['date'].dt.quarter print("从日期提取的特征:n", df_feature.head()) # 创建滞后特征 df_feature['sales_lag_1'] = df_feature['sales'].shift(1) df_feature['sales_lag_7'] = df_feature['sales'].shift(7) print("添加滞后特征后的数据:n", df_feature.head(10)) # 创建滚动统计特征 df_feature['sales_rolling_mean_7'] = df_feature['sales'].rolling(window=7).mean() df_feature['sales_rolling_std_7'] = df_feature['sales'].rolling(window=7).std() df_feature['sales_rolling_max_7'] = df_feature['sales'].rolling(window=7).max() df_feature['sales_rolling_min_7'] = df_feature['sales'].rolling(window=7).min() print("添加滚动统计特征后的数据:n", df_feature.head(10)) # 创建多项式特征 from sklearn.preprocessing import PolynomialFeatures poly = PolynomialFeatures(degree=2, include_bias=False) poly_features = poly.fit_transform(df_feature[['sales', 'sales_lag_1']].dropna()) poly_df = pd.DataFrame(poly_features, columns=poly.get_feature_names(['sales', 'sales_lag_1'])) print("多项式特征:n", poly_df.head()) 

数据分组与聚合

数据分组与聚合是数据分析中常用的操作,用于将数据分成不同的组,然后对每组应用聚合函数。

# 创建示例数据 np.random.seed(42) data = { 'department': ['HR', 'IT', 'Finance', 'HR', 'IT', 'Finance', 'HR', 'IT', 'Finance'], 'employee_id': range(1, 10), 'salary': np.random.randint(50000, 100000, 9), 'years_of_service': np.random.randint(1, 10, 9) } df_group = pd.DataFrame(data) # 按部门分组并计算平均薪资 dept_avg_salary = df_group.groupby('department')['salary'].mean() print("各部门平均薪资:n", dept_avg_salary) # 按部门分组并计算多个统计量 dept_stats = df_group.groupby('department').agg({ 'salary': ['mean', 'median', 'std', 'min', 'max'], 'years_of_service': ['mean', 'median'] }) print("各部门详细统计:n", dept_stats) # 自定义聚合函数 def salary_range(x): return x.max() - x.min() dept_custom = df_group.groupby('department').agg({ 'salary': salary_range, 'employee_id': 'count' }) print("自定义聚合:n", dept_custom) # 多级分组 data = { 'department': ['HR', 'IT', 'Finance', 'HR', 'IT', 'Finance', 'HR', 'IT', 'Finance'], 'level': ['Junior', 'Senior', 'Junior', 'Senior', 'Junior', 'Senior', 'Junior', 'Senior', 'Junior'], 'salary': np.random.randint(50000, 100000, 9), 'years_of_service': np.random.randint(1, 10, 9) } df_multi_group = pd.DataFrame(data) multi_group = df_multi_group.groupby(['department', 'level']).mean() print("多级分组:n", multi_group) # 透视表 pivot_table = pd.pivot_table(df_multi_group, values='salary', index='department', columns='level', aggfunc='mean') print("透视表:n", pivot_table) 

数据分析与探索

数据清洗和预处理完成后,接下来进行数据分析和探索,以发现数据中的模式、趋势和关系。

描述性统计分析

描述性统计是数据分析的基础,用于总结和描述数据的基本特征。

# 创建示例数据 np.random.seed(42) data = { 'product': ['A', 'B', 'C', 'D', 'E'] * 20, 'region': ['North', 'South', 'East', 'West'] * 25, 'sales': np.random.randint(100, 1000, 100), 'profit': np.random.randint(10, 100, 100), 'quantity': np.random.randint(1, 20, 100) } df_analysis = pd.DataFrame(data) # 基本统计描述 print("基本统计描述:n", df_analysis.describe()) # 计算偏度和峰度 print("偏度:n", df_analysis.skew()) print("峰度:n", df_analysis.kurtosis()) # 计算相关系数 print("相关系数矩阵:n", df_analysis.corr()) # 计算协方差 print("协方差矩阵:n", df_analysis.cov()) # 计算分位数 print("分位数:n", df_analysis.quantile([0.25, 0.5, 0.75])) # 计算变异系数 cv = lambda x: np.std(x, ddof=1) / np.mean(x) print("变异系数:n", df_analysis[['sales', 'profit', 'quantity']].apply(cv)) 

相关性分析

相关性分析用于研究变量之间的线性关系强度和方向。

# 计算相关系数矩阵 corr_matrix = df_analysis[['sales', 'profit', 'quantity']].corr() print("相关系数矩阵:n", corr_matrix) # 可视化相关系数矩阵 import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize=(8, 6)) sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1) plt.title('相关系数热力图') plt.show() # 计算不同类型的相关系数 # Pearson相关系数(线性相关) pearson_corr = df_analysis[['sales', 'profit', 'quantity']].corr(method='pearson') print("Pearson相关系数:n", pearson_corr) # Spearman相关系数(单调相关) spearman_corr = df_analysis[['sales', 'profit', 'quantity']].corr(method='spearman') print("Spearman相关系数:n", spearman_corr) # Kendall相关系数(秩相关) kendall_corr = df_analysis[['sales', 'profit', 'quantity']].corr(method='kendall') print("Kendall相关系数:n", kendall_corr) # 计算p值 from scipy.stats import pearsonr, spearmanr # Pearson相关系数和p值 pearson_p = df_analysis[['sales', 'profit', 'quantity']].corr(method=lambda x, y: pearsonr(x, y)[1]) print("Pearson相关系数的p值:n", pearson_p) # Spearman相关系数和p值 spearman_p = df_analysis[['sales', 'profit', 'quantity']].corr(method=lambda x, y: spearmanr(x, y)[1]) print("Spearman相关系数的p值:n", spearman_p) 

假设检验

假设检验是统计推断的重要方法,用于判断样本数据是否支持某个关于总体的假设。

# 创建示例数据 np.random.seed(42) group_a = np.random.normal(100, 15, 30) group_b = np.random.normal(110, 15, 30) df_test = pd.DataFrame({ 'value': np.concatenate([group_a, group_b]), 'group': ['A'] * 30 + ['B'] * 30 }) # t检验(比较两组均值是否相等) from scipy.stats import ttest_ind t_stat, p_value = ttest_ind(df_test[df_test['group'] == 'A']['value'], df_test[df_test['group'] == 'B']['value']) print(f"t检验结果: t统计量 = {t_stat}, p值 = {p_value}") # 方差分析(ANOVA,比较多组均值是否相等) from scipy.stats import f_oneway group_c = np.random.normal(105, 15, 30) df_anova = pd.DataFrame({ 'value': np.concatenate([group_a, group_b, group_c]), 'group': ['A'] * 30 + ['B'] * 30 + ['C'] * 30 }) f_stat, p_value = f_oneway( df_anova[df_anova['group'] == 'A']['value'], df_anova[df_anova['group'] == 'B']['value'], df_anova[df_anova['group'] == 'C']['value'] ) print(f"方差分析结果: F统计量 = {f_stat}, p值 = {p_value}") # 卡方检验(检验分类变量的独立性) from scipy.stats import chi2_contingency contingency_table = pd.crosstab(df_analysis['product'], df_analysis['region']) print("列联表:n", contingency_table) chi2, p_value, dof, expected = chi2_contingency(contingency_table) print(f"卡方检验结果: 卡方值 = {chi2}, p值 = {p_value}, 自由度 = {dof}") # 正态性检验 from scipy.stats import shapiro, normaltest # Shapiro-Wilk检验(适用于小样本) shapiro_stat, shapiro_p = shapiro(df_test['value']) print(f"Shapiro-Wilk检验结果: 统计量 = {shapiro_stat}, p值 = {shapiro_p}") # D'Agostino's K-squared检验(适用于大样本) k2_stat, k2_p = normaltest(df_test['value']) print(f"D'Agostino's K-squared检验结果: 统计量 = {k2_stat}, p值 = {k2_p}") 

时间序列分析

时间序列分析是研究按时间顺序排列的数据点,以识别其中的模式、趋势和季节性。

# 创建时间序列数据 np.random.seed(42) dates = pd.date_range(start='2020-01-01', end='2022-12-31', freq='D') trend = np.linspace(100, 200, len(dates)) seasonality = 10 * np.sin(np.arange(len(dates)) * 2 * np.pi / 365.25) noise = np.random.normal(0, 5, len(dates)) values = trend + seasonality + noise df_time = pd.DataFrame({'date': dates, 'value': values}) df_time.set_index('date', inplace=True) # 绘制时间序列 plt.figure(figsize=(12, 6)) df_time['value'].plot() plt.title('时间序列数据') plt.xlabel('日期') plt.ylabel('值') plt.show() # 移动平均 df_time['MA_7'] = df_time['value'].rolling(window=7).mean() df_time['MA_30'] = df_time['value'].rolling(window=30).mean() plt.figure(figsize=(12, 6)) df_time['value'].plot(alpha=0.5, label='原始数据') df_time['MA_7'].plot(label='7天移动平均') df_time['MA_30'].plot(label='30天移动平均') plt.title('移动平均') plt.xlabel('日期') plt.ylabel('值') plt.legend() plt.show() # 季节性分解 from statsmodels.tsa.seasonal import seasonal_decompose # 使用月度数据进行分解 df_monthly = df_time['value'].resample('M').mean() result = seasonal_decompose(df_monthly, model='additive') plt.figure(figsize=(12, 8)) plt.subplot(411) plt.plot(result.observed, label='观测值') plt.legend() plt.subplot(412) plt.plot(result.trend, label='趋势') plt.legend() plt.subplot(413) plt.plot(result.seasonal, label='季节性') plt.legend() plt.subplot(414) plt.plot(result.resid, label='残差') plt.legend() plt.tight_layout() plt.show() # 自相关和偏自相关分析 from statsmodels.graphics.tsaplots import plot_acf, plot_pacf plt.figure(figsize=(12, 6)) plt.subplot(211) plot_acf(df_time['value'].dropna(), lags=40, ax=plt.gca()) plt.title('自相关函数(ACF)') plt.subplot(212) plot_pacf(df_time['value'].dropna(), lags=40, ax=plt.gca()) plt.title('偏自相关函数(PACF)') plt.tight_layout() plt.show() # 平稳性检验 from statsmodels.tsa.stattools import adfuller adf_result = adfuller(df_time['value'].dropna()) print(f'ADF统计量: {adf_result[0]}') print(f'p值: {adf_result[1]}') print('临界值:') for key, value in adf_result[4].items(): print(f' {key}: {value}') 

数据可视化

数据可视化是数据分析的重要环节,通过图形化方式展示数据,可以更直观地发现数据中的模式和关系。pandas可以与matplotlib、seaborn等可视化库结合使用,创建各种类型的图表。

基本图表

折线图

折线图适合展示随时间变化的数据趋势。

# 创建示例数据 np.random.seed(42) dates = pd.date_range(start='2020-01-01', end='2020-12-31') sales = np.cumsum(np.random.randint(50, 200, size=len(dates))) df_line = pd.DataFrame({'date': dates, 'sales': sales}) # 使用pandas内置绘图功能 df_line.plot(x='date', y='sales', figsize=(12, 6), title='2020年销售额趋势') plt.ylabel('销售额') plt.grid(True) plt.show() # 使用matplotlib plt.figure(figsize=(12, 6)) plt.plot(df_line['date'], df_line['sales']) plt.title('2020年销售额趋势') plt.xlabel('日期') plt.ylabel('销售额') plt.grid(True) plt.show() 

柱状图

柱状图适合比较不同类别的数据。

# 创建示例数据 data = { 'product': ['A', 'B', 'C', 'D', 'E'], 'sales': [250, 350, 200, 400, 300], 'profit': [50, 70, 40, 80, 60] } df_bar = pd.DataFrame(data) # 使用pandas内置绘图功能 df_bar.plot(x='product', y=['sales', 'profit'], kind='bar', figsize=(12, 6), title='产品销售额与利润') plt.ylabel('金额') plt.grid(True, axis='y') plt.show() # 使用seaborn plt.figure(figsize=(12, 6)) sns.barplot(x='product', y='sales', data=df_bar, color='blue', label='销售额') sns.barplot(x='product', y='profit', data=df_bar, color='red', label='利润') plt.title('产品销售额与利润') plt.ylabel('金额') plt.legend() plt.grid(True, axis='y') plt.show() 

散点图

散点图适合展示两个连续变量之间的关系。

# 创建示例数据 np.random.seed(42) n = 100 advertising = np.random.uniform(10, 100, n) sales = 50 + 5 * advertising + np.random.normal(0, 20, n) df_scatter = pd.DataFrame({'advertising': advertising, 'sales': sales}) # 使用pandas内置绘图功能 df_scatter.plot(x='advertising', y='sales', kind='scatter', figsize=(10, 8), title='广告投入与销售额关系') plt.grid(True) plt.show() # 使用seaborn plt.figure(figsize=(10, 8)) sns.scatterplot(x='advertising', y='sales', data=df_scatter) plt.title('广告投入与销售额关系') plt.grid(True) plt.show() # 添加回归线 plt.figure(figsize=(10, 8)) sns.regplot(x='advertising', y='sales', data=df_scatter) plt.title('广告投入与销售额关系(带回归线)') plt.grid(True) plt.show() 

直方图

直方图适合展示数据的分布情况。

# 创建示例数据 np.random.seed(42) data = np.concatenate([ np.random.normal(100, 15, 500), np.random.normal(150, 20, 300) ]) df_hist = pd.DataFrame({'value': data}) # 使用pandas内置绘图功能 df_hist['value'].plot(kind='hist', bins=30, figsize=(10, 8), title='数据分布直方图') plt.xlabel('值') plt.ylabel('频数') plt.grid(True) plt.show() # 使用seaborn plt.figure(figsize=(10, 8)) sns.histplot(df_hist['value'], bins=30, kde=True) plt.title('数据分布直方图(带密度曲线)') plt.xlabel('值') plt.ylabel('频数') plt.grid(True) plt.show() 

箱线图

箱线图适合展示数据的分布和异常值。

# 创建示例数据 np.random.seed(42) data = { 'group': ['A'] * 100 + ['B'] * 100 + ['C'] * 100, 'value': np.concatenate([ np.random.normal(100, 15, 100), np.random.normal(120, 20, 100), np.random.normal(80, 10, 100) ]) } df_box = pd.DataFrame(data) # 使用pandas内置绘图功能 df_box.boxplot(by='group', column='value', figsize=(10, 8)) plt.title('各组的值分布') plt.suptitle('') # 删除默认标题 plt.xlabel('组') plt.ylabel('值') plt.grid(True) plt.show() # 使用seaborn plt.figure(figsize=(10, 8)) sns.boxplot(x='group', y='value', data=df_box) plt.title('各组的值分布') plt.xlabel('组') plt.ylabel('值') plt.grid(True) plt.show() 

高级可视化

热力图

热力图适合展示矩阵数据,如相关系数矩阵。

# 创建示例数据 np.random.seed(42) variables = ['Var1', 'Var2', 'Var3', 'Var4', 'Var5'] data = np.random.randn(100, 5) df_heatmap = pd.DataFrame(data, columns=variables) # 计算相关系数矩阵 corr_matrix = df_heatmap.corr() # 使用seaborn绘制热力图 plt.figure(figsize=(10, 8)) sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1) plt.title('变量相关系数热力图') plt.show() 

成对关系图

成对关系图可以同时展示多个变量两两之间的关系。

# 创建示例数据 np.random.seed(42) data = { 'A': np.random.normal(0, 1, 100), 'B': np.random.normal(5, 2, 100), 'C': np.random.normal(-2, 1.5, 100), 'D': np.random.normal(3, 1, 100), 'E': np.random.choice(['X', 'Y', 'Z'], 100) } df_pairplot = pd.DataFrame(data) # 使用seaborn绘制成对关系图 sns.pairplot(df_pairplot, hue='E', diag_kind='kde') plt.suptitle('变量成对关系图', y=1.02) plt.show() 

多子图

多子图可以在一个图形中展示多个相关的图表。

# 创建示例数据 np.random.seed(42) dates = pd.date_range(start='2020-01-01', end='2020-12-31') sales = np.cumsum(np.random.randint(50, 200, size=len(dates))) advertising = np.random.uniform(10, 100, len(dates)) profit = sales * 0.2 + np.random.normal(0, 10, len(dates)) df_multi = pd.DataFrame({ 'date': dates, 'sales': sales, 'advertising': advertising, 'profit': profit }) # 创建多子图 fig, axes = plt.subplots(3, 1, figsize=(12, 15), sharex=True) # 销售额趋势 axes[0].plot(df_multi['date'], df_multi['sales'], 'b-') axes[0].set_title('销售额趋势') axes[0].set_ylabel('销售额') axes[0].grid(True) # 广告投入 axes[1].plot(df_multi['date'], df_multi['advertising'], 'g-') axes[1].set_title('广告投入') axes[1].set_ylabel('广告投入') axes[1].grid(True) # 利润 axes[2].plot(df_multi['date'], df_multi['profit'], 'r-') axes[2].set_title('利润') axes[2].set_ylabel('利润') axes[2].set_xlabel('日期') axes[2].grid(True) plt.tight_layout() plt.show() 

交互式可视化

使用plotly库可以创建交互式可视化图表。

# 安装plotly(如果未安装) # !pip install plotly import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots # 创建示例数据 np.random.seed(42) data = { 'date': pd.date_range(start='2020-01-01', end='2020-12-31'), 'sales': np.cumsum(np.random.randint(50, 200, size=366)), 'category': np.random.choice(['A', 'B', 'C'], 366), 'region': np.random.choice(['North', 'South', 'East', 'West'], 366) } df_interactive = pd.DataFrame(data) # 创建交互式折线图 fig = px.line(df_interactive, x='date', y='sales', title='2020年销售额趋势') fig.update_layout( xaxis_title='日期', yaxis_title='销售额', hovermode='x unified' ) fig.show() # 创建交互式柱状图 sales_by_category = df_interactive.groupby(['date', 'category'])['sales'].sum().reset_index() fig = px.bar(sales_by_category, x='date', y='sales', color='category', title='各类别销售额') fig.update_layout( xaxis_title='日期', yaxis_title='销售额', hovermode='x unified' ) fig.show() # 创建交互式散点图 fig = px.scatter( df_interactive, x='date', y='sales', color='category', size='sales', hover_name='region', title='销售额分布' ) fig.update_layout( xaxis_title='日期', yaxis_title='销售额' ) fig.show() # 创建交互式子图 fig = make_subplots( rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1, subplot_titles=('销售额', '广告投入') ) # 添加销售额折线图 fig.add_trace( go.Scatter(x=df_interactive['date'], y=df_interactive['sales'], name='销售额'), row=1, col=1 ) # 添加广告投入柱状图 fig.add_trace( go.Bar(x=df_interactive['date'], y=df_interactive['sales'] * 0.1, name='广告投入'), row=2, col=1 ) fig.update_layout( height=600, width=1000, title_text="销售额与广告投入关系", hovermode='x unified' ) fig.show() 

实战案例

为了更好地理解pandas在数据分析全流程中的应用,我们将通过一个完整的实战案例来展示从数据清洗到可视化的整个过程。

案例背景

假设我们是一家零售公司的数据分析师,需要分析销售数据,以了解销售趋势、产品表现和区域差异,并提供业务建议。数据集包含以下字段:

  • date: 销售日期
  • product_id: 产品ID
  • product_name: 产品名称
  • category: 产品类别
  • region: 销售区域
  • sales: 销售额
  • quantity: 销售数量
  • discount: 折扣率

数据加载与初步探索

# 创建模拟数据 np.random.seed(42) n_records = 1000 # 日期范围 start_date = pd.to_datetime('2020-01-01') end_date = pd.to_datetime('2022-12-31') dates = pd.date_range(start_date, end_date) # 产品信息 product_names = ['Laptop', 'Smartphone', 'Tablet', 'Monitor', 'Keyboard', 'Mouse', 'Headphones', 'Printer'] categories = ['Electronics', 'Electronics', 'Electronics', 'Electronics', 'Accessories', 'Accessories', 'Accessories', 'Electronics'] product_data = pd.DataFrame({ 'product_id': range(1, len(product_names) + 1), 'product_name': product_names, 'category': categories }) # 区域 regions = ['North', 'South', 'East', 'West'] # 生成销售数据 data = { 'date': np.random.choice(dates, n_records), 'product_id': np.random.choice(product_data['product_id'], n_records), 'region': np.random.choice(regions, n_records), 'sales': np.random.uniform(100, 2000, n_records), 'quantity': np.random.randint(1, 10, n_records), 'discount': np.random.uniform(0, 0.3, n_records) } # 创建DataFrame df_sales = pd.DataFrame(data) # 合并产品信息 df_sales = pd.merge(df_sales, product_data, on='product_id', how='left') # 添加一些缺失值和异常值 # 添加缺失值 missing_indices = np.random.choice(df_sales.index, size=int(0.05 * n_records), replace=False) df_sales.loc[missing_indices, 'discount'] = np.nan # 添加异常值 outlier_indices = np.random.choice(df_sales.index, size=int(0.02 * n_records), replace=False) df_sales.loc[outlier_indices, 'sales'] = np.random.uniform(5000, 10000, size=len(outlier_indices)) # 添加重复记录 duplicate_indices = np.random.choice(df_sales.index, size=int(0.03 * n_records), replace=False) df_duplicates = df_sales.loc[duplicate_indices] df_sales = pd.concat([df_sales, df_duplicates]) # 重置索引 df_sales = df_sales.reset_index(drop=True) # 查看数据前几行 print("数据前5行:") print(df_sales.head()) # 查看数据基本信息 print("n数据基本信息:") print(df_sales.info()) # 查看数据统计摘要 print("n数据统计摘要:") print(df_sales.describe()) 

数据清洗

# 处理重复值 print(f"原始数据行数: {len(df_sales)}") df_sales_clean = df_sales.drop_duplicates() print(f"删除重复值后行数: {len(df_sales_clean)}") # 处理缺失值 print("n缺失值统计:") print(df_sales_clean.isnull().sum()) # 填充缺失的折扣率为0 df_sales_clean['discount'] = df_sales_clean['discount'].fillna(0) # 再次检查缺失值 print("n填充缺失值后的缺失值统计:") print(df_sales_clean.isnull().sum()) # 处理异常值 # 使用IQR方法检测销售额异常值 Q1 = df_sales_clean['sales'].quantile(0.25) Q3 = df_sales_clean['sales'].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR outliers = df_sales_clean[(df_sales_clean['sales'] < lower_bound) | (df_sales_clean['sales'] > upper_bound)] print(f"n销售额异常值数量: {len(outliers)}") # 将异常值替换为边界值 df_sales_clean.loc[df_sales_clean['sales'] < lower_bound, 'sales'] = lower_bound df_sales_clean.loc[df_sales_clean['sales'] > upper_bound, 'sales'] = upper_bound # 检查处理后的数据 print("n处理后的销售额统计:") print(df_sales_clean['sales'].describe()) # 数据类型转换 # 确保日期是datetime类型 df_sales_clean['date'] = pd.to_datetime(df_sales_clean['date']) # 添加时间特征 df_sales_clean['year'] = df_sales_clean['date'].dt.year df_sales_clean['month'] = df_sales_clean['date'].dt.month df_sales_clean['day'] = df_sales_clean['date'].dt.day df_sales_clean['dayofweek'] = df_sales_clean['date'].dt.dayofweek df_sales_clean['quarter'] = df_sales_clean['date'].dt.quarter # 添加计算字段 df_sales_clean['unit_price'] = df_sales_clean['sales'] / df_sales_clean['quantity'] df_sales_clean['discounted_sales'] = df_sales_clean['sales'] * (1 - df_sales_clean['discount']) # 查看处理后的数据 print("n处理后的数据前5行:") print(df_sales_clean.head()) 

数据分析与探索

# 销售趋势分析 # 按月份汇总销售数据 monthly_sales = df_sales_clean.groupby(['year', 'month']).agg({ 'sales': 'sum', 'discounted_sales': 'sum', 'quantity': 'sum' }).reset_index() # 创建年月列 monthly_sales['year_month'] = monthly_sales['year'].astype(str) + '-' + monthly_sales['month'].astype(str).str.zfill(2) # 可视化月度销售趋势 plt.figure(figsize=(14, 7)) plt.plot(monthly_sales['year_month'], monthly_sales['sales'], 'o-', label='总销售额') plt.plot(monthly_sales['year_month'], monthly_sales['discounted_sales'], 's-', label='折扣后销售额') plt.title('月度销售趋势') plt.xlabel('年月') plt.ylabel('销售额') plt.xticks(rotation=45) plt.legend() plt.grid(True) plt.tight_layout() plt.show() # 产品分析 # 按产品类别汇总销售数据 category_sales = df_sales_clean.groupby('category').agg({ 'sales': 'sum', 'discounted_sales': 'sum', 'quantity': 'sum' }).reset_index() # 计算各类别的销售额占比 category_sales['sales_pct'] = category_sales['sales'] / category_sales['sales'].sum() * 100 # 可视化各类别销售额 plt.figure(figsize=(12, 6)) sns.barplot(x='category', y='sales', data=category_sales) plt.title('各类别销售额') plt.xlabel('类别') plt.ylabel('销售额') plt.grid(True, axis='y') plt.tight_layout() plt.show() # 按产品名称汇总销售数据 product_sales = df_sales_clean.groupby('product_name').agg({ 'sales': 'sum', 'discounted_sales': 'sum', 'quantity': 'sum' }).reset_index().sort_values('sales', ascending=False) # 可视化产品销售额 plt.figure(figsize=(12, 6)) sns.barplot(x='product_name', y='sales', data=product_sales) plt.title('各产品销售额') plt.xlabel('产品名称') plt.ylabel('销售额') plt.xticks(rotation=45) plt.grid(True, axis='y') plt.tight_layout() plt.show() # 区域分析 # 按区域汇总销售数据 region_sales = df_sales_clean.groupby('region').agg({ 'sales': 'sum', 'discounted_sales': 'sum', 'quantity': 'sum' }).reset_index() # 可视化区域销售额 plt.figure(figsize=(10, 6)) sns.barplot(x='region', y='sales', data=region_sales) plt.title('各区域销售额') plt.xlabel('区域') plt.ylabel('销售额') plt.grid(True, axis='y') plt.tight_layout() plt.show() # 区域和类别的交叉分析 region_category_sales = df_sales_clean.groupby(['region', 'category']).agg({ 'sales': 'sum' }).reset_index() # 透视表 pivot_table = pd.pivot_table(region_category_sales, values='sales', index='region', columns='category', aggfunc='sum') # 可视化区域和类别的销售额热力图 plt.figure(figsize=(10, 6)) sns.heatmap(pivot_table, annot=True, fmt='.0f', cmap='YlGnBu') plt.title('各区域各类别销售额热力图') plt.xlabel('类别') plt.ylabel('区域') plt.tight_layout() plt.show() # 时间序列分析 # 按日期汇总销售数据 daily_sales = df_sales_clean.groupby('date').agg({ 'sales': 'sum', 'discounted_sales': 'sum', 'quantity': 'sum' }).reset_index() # 设置日期为索引 daily_sales.set_index('date', inplace=True) # 计算移动平均 daily_sales['MA_7'] = daily_sales['sales'].rolling(window=7).mean() daily_sales['MA_30'] = daily_sales['sales'].rolling(window=30).mean() # 可视化日销售额和移动平均 plt.figure(figsize=(14, 7)) plt.plot(daily_sales.index, daily_sales['sales'], alpha=0.5, label='日销售额') plt.plot(daily_sales.index, daily_sales['MA_7'], label='7天移动平均') plt.plot(daily_sales.index, daily_sales['MA_30'], label='30天移动平均') plt.title('日销售额及移动平均') plt.xlabel('日期') plt.ylabel('销售额') plt.legend() plt.grid(True) plt.tight_layout() plt.show() # 季节性分析 # 按月份汇总销售数据(不考虑年份) monthly_pattern = df_sales_clean.groupby('month').agg({ 'sales': 'mean' }).reset_index() # 可视化月度销售模式 plt.figure(figsize=(10, 6)) sns.barplot(x='month', y='sales', data=monthly_pattern) plt.title('月度销售模式') plt.xlabel('月份') plt.ylabel('平均销售额') plt.grid(True, axis='y') plt.tight_layout() plt.show() # 按星期汇总销售数据 weekly_pattern = df_sales_clean.groupby('dayofweek').agg({ 'sales': 'mean' }).reset_index() weekly_pattern['day_name'] = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] # 可视化星期销售模式 plt.figure(figsize=(10, 6)) sns.barplot(x='day_name', y='sales', data=weekly_pattern) plt.title('星期销售模式') plt.xlabel('星期') plt.ylabel('平均销售额') plt.grid(True, axis='y') plt.tight_layout() plt.show() 

深入分析与洞察

# 折扣分析 # 分析折扣对销售额的影响 # 创建折扣区间 df_sales_clean['discount_bin'] = pd.cut(df_sales_clean['discount'], bins=[0, 0.1, 0.2, 0.3], labels=['0-10%', '10-20%', '20-30%']) # 按折扣区间汇总 discount_analysis = df_sales_clean.groupby('discount_bin').agg({ 'sales': ['mean', 'count'], 'quantity': 'mean', 'unit_price': 'mean' }).reset_index() print("折扣分析:") print(discount_analysis) # 可视化折扣对销售额的影响 plt.figure(figsize=(10, 6)) sns.barplot(x='discount_bin', y=('sales', 'mean'), data=discount_analysis) plt.title('不同折扣区间的平均销售额') plt.xlabel('折扣区间') plt.ylabel('平均销售额') plt.grid(True, axis='y') plt.tight_layout() plt.show() # 产品组合分析 # 分析哪些产品经常一起销售 from itertools import combinations from collections import Counter # 按日期和区域分组,找出每次交易中的产品组合 transactions = df_sales_clean.groupby(['date', 'region'])['product_name'].apply(list).reset_index() # 生成产品组合 product_combinations = [] for products in transactions['product_name']: if len(products) > 1: # 生成所有可能的两两组合 for combo in combinations(sorted(set(products)), 2): product_combinations.append(combo) # 统计组合频率 combo_counts = Counter(product_combinations) top_combos = combo_counts.most_common(10) print("最常见的产品组合:") for combo, count in top_combos: print(f"{combo[0]} + {combo[1]}: {count}次") # 客户价值分析 # 假设每个区域代表一个客户群体 customer_value = df_sales_clean.groupby('region').agg({ 'sales': 'sum', 'quantity': 'sum', 'product_id': lambda x: len(set(x)) # 不同产品数量 }).reset_index() customer_value.columns = ['region', 'total_sales', 'total_quantity', 'unique_products'] customer_value['avg_order_value'] = customer_value['total_sales'] / customer_value['total_quantity'] print("n客户价值分析:") print(customer_value) # 可视化客户价值 plt.figure(figsize=(12, 6)) x = np.arange(len(customer_value['region'])) width = 0.25 plt.bar(x - width, customer_value['total_sales'], width, label='总销售额') plt.bar(x, customer_value['total_quantity'], width, label='总销售量') plt.bar(x + width, customer_value['unique_products'], width, label='独特产品数') plt.title('各区域客户价值') plt.xlabel('区域') plt.ylabel('值') plt.xticks(x, customer_value['region']) plt.legend() plt.grid(True, axis='y') plt.tight_layout() plt.show() # 增长率分析 # 计算同比增长率 yearly_sales = df_sales_clean.groupby('year')['sales'].sum().reset_index() yearly_sales['yoy_growth'] = yearly_sales['sales'].pct_change() * 100 print("n年度销售增长率:") print(yearly_sales) # 计算环比增长率 quarterly_sales = df_sales_clean.groupby(['year', 'quarter'])['sales'].sum().reset_index() quarterly_sales['quarter_label'] = quarterly_sales['year'].astype(str) + '-Q' + quarterly_sales['quarter'].astype(str) quarterly_sales['qoq_growth'] = quarterly_sales['sales'].pct_change() * 100 print("n季度销售增长率:") print(quarterly_sales[['quarter_label', 'sales', 'qoq_growth']]) # 可视化季度销售和增长率 fig, ax1 = plt.subplots(figsize=(14, 7)) color = 'tab:blue' ax1.set_xlabel('季度') ax1.set_ylabel('销售额', color=color) ax1.bar(quarterly_sales['quarter_label'], quarterly_sales['sales'], color=color, alpha=0.6) ax1.tick_params(axis='y', labelcolor=color) ax1.set_xticklabels(quarterly_sales['quarter_label'], rotation=45) ax2 = ax1.twinx() color = 'tab:red' ax2.set_ylabel('增长率(%)', color=color) ax2.plot(quarterly_sales['quarter_label'], quarterly_sales['qoq_growth'], color=color, marker='o') ax2.tick_params(axis='y', labelcolor=color) ax2.axhline(y=0, color='gray', linestyle='--') plt.title('季度销售额及环比增长率') fig.tight_layout() plt.show() 

综合可视化与报告

# 创建综合仪表板 fig = plt.figure(figsize=(20, 15)) gs = fig.add_gridspec(3, 3) # 1. 月度销售趋势 ax1 = fig.add_subplot(gs[0, :]) monthly_sales['year_month'] = pd.to_datetime(monthly_sales['year_month']) ax1.plot(monthly_sales['year_month'], monthly_sales['sales'], 'o-', label='总销售额') ax1.plot(monthly_sales['year_month'], monthly_sales['discounted_sales'], 's-', label='折扣后销售额') ax1.set_title('月度销售趋势') ax1.set_xlabel('年月') ax1.set_ylabel('销售额') ax1.legend() ax1.grid(True) # 2. 产品类别销售额 ax2 = fig.add_subplot(gs[1, 0]) sns.barplot(x='category', y='sales', data=category_sales, ax=ax2) ax2.set_title('各类别销售额') ax2.set_xlabel('类别') ax2.set_ylabel('销售额') ax2.grid(True, axis='y') # 3. 区域销售额 ax3 = fig.add_subplot(gs[1, 1]) sns.barplot(x='region', y='sales', data=region_sales, ax=ax3) ax3.set_title('各区域销售额') ax3.set_xlabel('区域') ax3.set_ylabel('销售额') ax3.grid(True, axis='y') # 4. 折扣分析 ax4 = fig.add_subplot(gs[1, 2]) sns.barplot(x='discount_bin', y=('sales', 'mean'), data=discount_analysis, ax=ax4) ax4.set_title('不同折扣区间的平均销售额') ax4.set_xlabel('折扣区间') ax4.set_ylabel('平均销售额') ax4.grid(True, axis='y') # 5. 月度销售模式 ax5 = fig.add_subplot(gs[2, 0]) sns.barplot(x='month', y='sales', data=monthly_pattern, ax=ax5) ax5.set_title('月度销售模式') ax5.set_xlabel('月份') ax5.set_ylabel('平均销售额') ax5.grid(True, axis='y') # 6. 星期销售模式 ax6 = fig.add_subplot(gs[2, 1]) sns.barplot(x='day_name', y='sales', data=weekly_pattern, ax=ax6) ax6.set_title('星期销售模式') ax6.set_xlabel('星期') ax6.set_ylabel('平均销售额') ax6.grid(True, axis='y') # 7. 区域和类别的销售额热力图 ax7 = fig.add_subplot(gs[2, 2]) sns.heatmap(pivot_table, annot=True, fmt='.0f', cmap='YlGnBu', ax=ax7) ax7.set_title('各区域各类别销售额热力图') ax7.set_xlabel('类别') ax7.set_ylabel('区域') plt.tight_layout() plt.savefig('sales_analysis_dashboard.png', dpi=300) plt.show() # 生成分析报告 report = f""" # 销售数据分析报告 ## 执行摘要 本报告分析了从{start_date.date()}到{end_date.date()}的销售数据,涵盖{len(product_data)}个产品在{len(regions)}个区域的销售情况。 ## 关键发现 ### 销售趋势 - 总销售额: {df_sales_clean['sales'].sum():,.2f} - 总销售量: {df_sales_clean['quantity'].sum():,} - 平均折扣率: {df_sales_clean['discount'].mean():.2%} ### 产品表现 - 销售额最高的产品类别: {category_sales.loc[category_sales['sales'].idxmax(), 'category']} - 销售额最高的产品: {product_sales.loc[product_sales['sales'].idxmax(), 'product_name']} - 销售额最高的区域: {region_sales.loc[region_sales['sales'].idxmax(), 'region']} ### 季节性模式 - 销售额最高的月份: {monthly_pattern.loc[monthly_pattern['sales'].idxmax(), 'month']}月 - 销售额最高的星期: {weekly_pattern.loc[weekly_pattern['sales'].idxmax(), 'day_name']} ### 增长情况 - 年度增长率: {yearly_sales.loc[yearly_sales.index == 1, 'yoy_growth'].values[0]:.2%} ## 详细分析 ### 产品分析 {product_sales.to_string(index=False)} ### 区域分析 {region_sales.to_string(index=False)} ### 折扣分析 {discount_analysis.to_string(index=False)} ## 建议 1. 针对{monthly_pattern.loc[monthly_pattern['sales'].idxmax(), 'month']}月和{weekly_pattern.loc[weekly_pattern['sales'].idxmax(), 'day_name']}的销售高峰,增加库存和营销资源。 2. 重点推广{product_sales.loc[product_sales['sales'].idxmax(), 'product_name']}产品,并考虑开发类似产品。 3. 在{region_sales.loc[region_sales['sales'].idxmin(), 'region']}区域增加营销活动,提高市场份额。 4. 评估折扣策略的效果,优化折扣区间以提高销售额和利润率。 """ print(report) 

总结与进阶学习资源

总结

本文全面介绍了pandas库在数据分析全流程中的应用,从数据清洗到可视化。我们学习了:

  1. pandas基础:包括Series和DataFrame数据结构、基本操作等。
  2. 数据清洗:处理缺失值、重复值、异常值和数据类型转换。
  3. 数据转换与预处理:标准化、归一化、特征编码和特征工程。
  4. 数据分析与探索:描述性统计、相关性分析、假设检验和时间序列分析。
  5. 数据可视化:基本图表和高级可视化技术。
  6. 实战案例:通过一个完整的零售数据分析案例,展示了从数据清洗到可视化的全流程。

pandas作为Python数据分析的核心库,提供了强大而灵活的工具,使得数据分析工作更加高效和便捷。掌握pandas的使用,对于任何数据分析师或数据科学家来说都是必不可少的技能。

进阶学习资源

  1. 官方文档

    • pandas官方文档:https://pandas.pydata.org/docs/
    • pandas用户指南:https://pandas.pydata.org/docs/user_guide/index.html
  2. 书籍

    • 《利用Python进行数据分析》by Wes McKinney(pandas创建者)
    • 《Python数据分析实战》by Fabio Nelli
    • 《Python数据科学手册》by Jake VanderPlas
  3. 在线课程

    • Coursera上的”Applied Data Science with Python”系列课程
    • Udemy上的”Pandas for Data Analysis”
    • DataCamp上的”Data Manipulation with pandas”
  4. 博客和教程

    • Real Python上的pandas教程:https://realpython.com/tutorials/pandas/
    • Towards Data Science上的pandas文章:https://towardsdatascience.com/tagged/pandas
    • Machine Learning Mastery上的pandas教程:https://machinelearningmastery.com/pandas/
  5. GitHub资源

    • pandas官方GitHub仓库:https://github.com/pandas-dev/pandas
    • Awesome pandas:https://github.com/timothykp/pandas_awesome
    • pandas-cookbook:https://github.com/jvns/pandas-cookbook
  6. 社区和论坛

    • Stack Overflow(标签:pandas)
    • Reddit的r/pandas社区
    • pandas官方邮件列表

通过不断学习和实践,您将能够更加熟练地使用pandas进行数据分析,并掌握更多高级技巧和最佳实践。祝您在数据分析的道路上取得成功!