|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
引言
在数据科学和分析领域,快速理解数据集的特征是任何分析项目的首要步骤。Pandas作为Python最流行的数据处理库,提供了强大的工具来简化这一过程。其中,describe()函数是一个特别有用的方法,它能够生成数据集的描述性统计摘要,帮助分析师迅速把握数据的核心特征。本文将深入探讨如何有效利用Pandas的describe()函数,从基础使用到高级技巧,帮助你提升数据分析效率,快速洞察数据集的关键特征。
Pandas describe()函数基础
基本语法与使用
Pandas的describe()函数是一个便捷的方法,用于生成数据集或数据系列的各种描述性统计信息。其基本语法非常简单:
- import pandas as pd
- # 对于整个DataFrame
- df.describe()
- # 对于单个Series
- df['column_name'].describe()
- # 包含特定百分位数
- df.describe(percentiles=[0.1, 0.5, 0.9])
复制代码
默认输出内容
对于数值型数据,describe()默认会输出以下统计指标:
• count: 非空值的数量
• mean: 平均值
• std: 标准差
• min: 最小值
• 25%: 第一四分位数(Q1)
• 50%: 中位数(Q2)
• 75%: 第三四分位数(Q3)
• max: 最大值
让我们通过一个实际例子来查看describe()的输出:
- import pandas as pd
- import numpy as np
- # 创建一个示例DataFrame
- np.random.seed(42)
- data = {
- 'Age': np.random.normal(40, 15, 1000).clip(18, 80),
- 'Income': np.random.lognormal(4, 0.5, 1000) * 1000,
- 'Score': np.random.normal(75, 10, 1000).clip(0, 100),
- 'Years_Experience': np.random.randint(0, 40, 1000)
- }
- df = pd.DataFrame(data)
- # 使用describe()函数
- print(df.describe())
复制代码
输出结果将类似于:
- Age Income Score Years_Experience
- count 1000.000000 1000.000000 1000.000000 1000.000000
- mean 40.028830 62058.896931 74.947868 19.531000
- std 14.896619 32198.542873 9.965612 11.565414
- min 18.000000 8226.840532 30.919690 0.000000
- 25% 29.000000 38958.855532 68.244632 9.000000
- 50% 40.085612 56733.843832 74.983825 20.000000
- 75% 51.000000 78701.789336 81.715020 29.000000
- max 80.000000 296421.847538 99.999990 39.000000
复制代码
不同数据类型的输出差异
describe()函数会根据数据类型自动调整输出的统计指标:
1. 数值型数据:如上所示,包含计数、均值、标准差等八项指标。
2. 对象/字符串类型数据:输出计数、唯一值数量、最频繁出现的值及其频率。
- # 添加一个分类列
- df['Department'] = np.random.choice(['HR', 'IT', 'Finance', 'Marketing'], 1000)
- # 查看所有列的描述性统计
- print(df.describe(include='all'))
复制代码
对于’Department’列,输出会包含:
• count: 非空值数量
• unique: 唯一值数量
• top: 最频繁出现的值
• freq: 最频繁值的出现次数
自定义包含的数据类型
你可以使用include和exclude参数来控制describe()函数处理的数据类型:
- # 只包含数值型列
- df.describe(include=[np.number])
- # 只包含对象类型列
- df.describe(include=[object])
- # 排除数值型列
- df.describe(exclude=[np.number])
- # 包含多种类型
- df.describe(include=[np.number, 'category'])
复制代码
深入理解describe()的输出
理解数值型数据的统计指标
让我们详细解释每个统计指标的含义及其在数据分析中的应用:
计数表示每列中非空值的数量。这是检查数据完整性的第一步:
- # 检查缺失值
- missing_values = df.isnull().sum()
- print("缺失值数量:")
- print(missing_values)
- # 计算完整度
- completeness = (1 - df.isnull().mean()) * 100
- print("\n数据完整度(%):")
- print(completeness)
复制代码
均值和中位数都是衡量数据中心趋势的指标,但它们对不同数据分布的敏感度不同:
- # 比较均值和中位数
- mean_median_comparison = pd.DataFrame({
- 'Mean': df.mean(numeric_only=True),
- 'Median': df.median(numeric_only=True),
- 'Difference': df.mean(numeric_only=True) - df.median(numeric_only=True),
- 'Percent_Difference': (df.mean(numeric_only=True) - df.median(numeric_only=True)) / df.median(numeric_only=True) * 100
- })
- print(mean_median_comparison)
复制代码
当均值显著大于中位数时,表明数据右偏(有较大的异常值);当均值显著小于中位数时,表明数据左偏。
标准差衡量数据的离散程度:
- # 计算变异系数(标准差/均值),用于比较不同量纲数据的离散程度
- coefficients_of_variation = df.std(numeric_only=True) / df.mean(numeric_only=True)
- print("变异系数:")
- print(coefficients_of_variation)
复制代码
四分位数将数据分为四个等份,有助于理解数据分布:
- # 计算四分位距(IQR)
- Q1 = df.quantile(0.25, numeric_only=True)
- Q3 = df.quantile(0.75, numeric_only=True)
- IQR = Q3 - Q1
- print("四分位距(IQR):")
- print(IQR)
- # 使用IQR检测异常值
- lower_bound = Q1 - 1.5 * IQR
- upper_bound = Q3 + 1.5 * IQR
- outliers = ((df.select_dtypes(include=[np.number]) < lower_bound) |
- (df.select_dtypes(include=[np.number]) > upper_bound)).sum()
- print("\n异常值数量:")
- print(outliers)
复制代码
极值提供了数据的范围:
- # 计算数值范围
- data_range = df.max(numeric_only=True) - df.min(numeric_only=True)
- print("数值范围:")
- print(data_range)
复制代码
理解分类数据的统计指标
对于分类数据,describe()提供了不同的统计指标:
- # 分析分类数据
- categorical_summary = df['Department'].describe()
- print(categorical_summary)
- # 获取更详细的分类统计
- department_counts = df['Department'].value_counts()
- department_percentages = df['Department'].value_counts(normalize=True) * 100
- print("\n部门计数:")
- print(department_counts)
- print("\n部门百分比:")
- print(department_percentages)
复制代码
时间序列数据的描述性统计
对于时间序列数据,describe()同样有用:
- # 创建时间序列数据示例
- date_range = pd.date_range(start='2020-01-01', end='2022-12-31', freq='D')
- ts_data = {
- 'Date': date_range,
- 'Sales': np.random.poisson(100, len(date_range)) + np.random.normal(0, 10, len(date_range)),
- 'Customers': np.random.randint(10, 100, len(date_range))
- }
- ts_df = pd.DataFrame(ts_data)
- ts_df.set_index('Date', inplace=True)
- # 按时间分组分析
- monthly_data = ts_df.resample('M').sum()
- print("月度数据描述:")
- print(monthly_data.describe())
- # 按星期几分析
- ts_df['DayOfWeek'] = ts_df.index.dayofweek
- weekday_analysis = ts_df.groupby('DayOfWeek').mean()
- print("\n按星期几的平均值:")
- print(weekday_analysis)
复制代码
实用技巧与案例
1. 自定义百分位数
默认情况下,describe()提供25%, 50%, 和75%的百分位数。你可以自定义这些百分位数以获得更详细的分布信息:
- # 自定义百分位数
- custom_percentiles = [0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95]
- custom_desc = df.describe(percentiles=custom_percentiles)
- print(custom_desc)
- # 专注于特定百分位数范围
- def percentile_range_analysis(df, column, lower_p=0.1, upper_p=0.9):
- lower_val = df[column].quantile(lower_p)
- upper_val = df[column].quantile(upper_p)
-
- middle_range = df[(df[column] >= lower_val) & (df[column] <= upper_val)]
-
- analysis = {
- f'{lower_p*100:.0f}th Percentile': lower_val,
- f'{upper_p*100:.0f}th Percentile': upper_val,
- 'Range Width': upper_val - lower_val,
- 'Data Points in Range': len(middle_range),
- 'Percentage in Range': len(middle_range) / len(df) * 100
- }
-
- return pd.Series(analysis)
- # 对Income列应用百分位范围分析
- income_analysis = percentile_range_analysis(df, 'Income', 0.1, 0.9)
- print("\n收入百分位范围分析:")
- print(income_analysis)
复制代码
2. 处理缺失值
describe()自动忽略缺失值,但有时我们需要更详细地了解缺失值的模式:
- # 添加一些缺失值
- df_with_missing = df.copy()
- df_with_missing.loc[np.random.choice(df.index, 50), 'Income'] = np.nan
- df_with_missing.loc[np.random.choice(df.index, 30), 'Score'] = np.nan
- # 缺失值分析
- def missing_value_analysis(df):
- missing_count = df.isnull().sum()
- missing_percentage = (df.isnull().mean() * 100).round(2)
-
- missing_df = pd.DataFrame({
- 'Missing_Count': missing_count,
- 'Missing_Percentage': missing_percentage
- })
-
- return missing_df[missing_df['Missing_Count'] > 0].sort_values('Missing_Percentage', ascending=False)
- print("缺失值分析:")
- print(missing_value_analysis(df_with_missing))
- # 比较有缺失值和没有缺失值的统计
- print("\n完整数据的描述性统计:")
- print(df.describe())
- print("\n有缺失数据的描述性统计:")
- print(df_with_missing.describe())
复制代码
3. 分组描述性统计
分组分析是理解数据子集差异的强大工具:
- # 按部门分组分析
- grouped_desc = df.groupby('Department').describe()
- print(grouped_desc)
- # 更简洁的分组统计
- def grouped_stats(df, group_col, value_cols):
- stats = df.groupby(group_col)[value_cols].agg(['count', 'mean', 'std', 'min', 'max'])
- return stats
- numeric_cols = ['Age', 'Income', 'Score', 'Years_Experience']
- print("\n按部门的简洁统计:")
- print(grouped_stats(df, 'Department', numeric_cols))
- # 分组比较可视化
- import matplotlib.pyplot as plt
- import seaborn as sns
- plt.figure(figsize=(12, 6))
- sns.boxplot(x='Department', y='Income', data=df)
- plt.title('各部门收入分布')
- plt.show()
复制代码
4. 可视化describe()结果
将describe()的结果可视化可以更直观地理解数据分布:
- # 将describe()结果热力图可视化
- def visualize_describe(desc_df):
- # 标准化数据以便更好地可视化
- desc_normalized = desc_df.copy()
- for col in desc_normalized.columns:
- if desc_normalized[col].max() > desc_normalized[col].min():
- desc_normalized[col] = (desc_normalized[col] - desc_normalized[col].min()) / (desc_normalized[col].max() - desc_normalized[col].min())
-
- plt.figure(figsize=(10, 6))
- sns.heatmap(desc_normalized, annot=True, cmap='YlGnBu', fmt='.2f')
- plt.title('标准化描述性统计热力图')
- plt.show()
- # 可视化数值列的描述性统计
- numeric_desc = df.describe()
- visualize_describe(numeric_desc)
- # 创建分布图
- def plot_distributions(df, cols):
- plt.figure(figsize=(15, 10))
- for i, col in enumerate(cols, 1):
- plt.subplot(2, 2, i)
- sns.histplot(df[col], kde=True)
- plt.title(f'{col} 分布')
-
- # 添加均值和中位数线
- plt.axvline(df[col].mean(), color='r', linestyle='--', label='Mean')
- plt.axvline(df[col].median(), color='g', linestyle='-', label='Median')
- plt.legend()
-
- plt.tight_layout()
- plt.show()
- plot_distributions(df, ['Age', 'Income', 'Score', 'Years_Experience'])
复制代码
5. 高级分析技巧
结合describe()与其他Pandas功能,可以进行更深入的分析:
- # 相关性分析
- correlation_matrix = df.corr()
- print("相关性矩阵:")
- print(correlation_matrix)
- # 可视化相关性矩阵
- plt.figure(figsize=(10, 8))
- sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f')
- plt.title('特征相关性热力图')
- plt.show()
- # 偏度和峰度分析
- from scipy import stats
- def distribution_analysis(df):
- skewness = df.skew()
- kurtosis = df.kurtosis()
-
- dist_analysis = pd.DataFrame({
- 'Skewness': skewness,
- 'Kurtosis': kurtosis
- })
-
- # 解释偏度
- def interpret_skewness(val):
- if val > 1:
- return "高度右偏"
- elif val > 0.5:
- return "中度右偏"
- elif val < -1:
- return "高度左偏"
- elif val < -0.5:
- return "中度左偏"
- else:
- return "相对对称"
-
- # 解释峰度
- def interpret_kurtosis(val):
- if val > 1:
- return "尖峰分布"
- elif val < -1:
- return "平峰分布"
- else:
- return "接近正态分布"
-
- dist_analysis['Skewness_Interpretation'] = dist_analysis['Skewness'].apply(interpret_skewness)
- dist_analysis['Kurtosis_Interpretation'] = dist_analysis['Kurtosis'].apply(interpret_kurtosis)
-
- return dist_analysis
- print("\n分布分析:")
- print(distribution_analysis(df.select_dtypes(include=[np.number])))
复制代码
提升数据分析效率的方法
1. 批量分析多个数据集
当你需要分析多个相似的数据集时,可以创建一个函数来自动化这个过程:
- def analyze_multiple_datasets(data_dict):
- results = {}
-
- for name, df in data_dict.items():
- # 基本描述性统计
- desc_stats = df.describe()
-
- # 缺失值分析
- missing_stats = missing_value_analysis(df)
-
- # 分布分析
- dist_stats = distribution_analysis(df.select_dtypes(include=[np.number]))
-
- # 相关性分析(仅数值列)
- numeric_cols = df.select_dtypes(include=[np.number]).columns
- if len(numeric_cols) > 1:
- corr_matrix = df[numeric_cols].corr()
- # 找出强相关(|correlation| > 0.7)
- strong_corrs = corr_matrix.abs().stack().sort_values(ascending=False)
- strong_corrs = strong_corrs[(strong_corrs > 0.7) & (strong_corrs < 1.0)]
- else:
- strong_corrs = "无多个数值列用于相关性分析"
-
- results[name] = {
- 'Descriptive_Stats': desc_stats,
- 'Missing_Values': missing_stats,
- 'Distribution_Analysis': dist_stats,
- 'Strong_Correlations': strong_corrs
- }
-
- return results
- # 示例:创建多个数据集进行分析
- dataset1 = df.copy()
- dataset2 = df.copy()
- dataset2['Income'] = dataset2['Income'] * 1.5 + np.random.normal(0, 5000, len(dataset2))
- datasets = {
- 'Original_Data': dataset1,
- 'Modified_Income_Data': dataset2
- }
- analysis_results = analyze_multiple_datasets(datasets)
- # 打印第一个数据集的分析结果
- print("原始数据集分析结果:")
- print("\n描述性统计:")
- print(analysis_results['Original_Data']['Descriptive_Stats'])
- print("\n缺失值分析:")
- print(analysis_results['Original_Data']['Missing_Values'])
复制代码
2. 自动化报告生成
将分析结果整合为自动化报告可以大大提高效率:
- def generate_data_report(df, title="数据分析报告"):
- """生成数据分析报告"""
- report = f"# {title}\n\n"
-
- # 数据集基本信息
- report += "## 数据集基本信息\n\n"
- report += f"- 行数: {df.shape[0]}\n"
- report += f"- 列数: {df.shape[1]}\n"
- report += f"- 数据类型:\n"
- for dtype, count in df.dtypes.value_counts().items():
- report += f" - {dtype}: {count} 列\n"
-
- # 缺失值分析
- report += "\n## 缺失值分析\n\n"
- missing = missing_value_analysis(df)
- if len(missing) > 0:
- report += missing.to_markdown()
- report += "\n\n"
- else:
- report += "数据集中没有缺失值。\n\n"
-
- # 数值列分析
- numeric_cols = df.select_dtypes(include=[np.number]).columns
- if len(numeric_cols) > 0:
- report += "## 数值列描述性统计\n\n"
- report += df[numeric_cols].describe().to_markdown()
- report += "\n\n"
-
- report += "## 分布分析\n\n"
- dist_analysis = distribution_analysis(df[numeric_cols])
- report += dist_analysis.to_markdown()
- report += "\n\n"
-
- # 分类列分析
- categorical_cols = df.select_dtypes(include=['object', 'category']).columns
- if len(categorical_cols) > 0:
- report += "## 分类列分析\n\n"
- for col in categorical_cols:
- report += f"### {col}\n\n"
- value_counts = df[col].value_counts()
- report += value_counts.to_markdown()
- report += "\n\n"
-
- # 相关性分析
- if len(numeric_cols) > 1:
- report += "## 相关性分析\n\n"
- corr_matrix = df[numeric_cols].corr()
- report += "相关性矩阵:\n\n"
- report += corr_matrix.to_markdown()
- report += "\n\n"
-
- # 找出强相关
- strong_corrs = corr_matrix.abs().stack().sort_values(ascending=False)
- strong_corrs = strong_corrs[(strong_corrs > 0.7) & (strong_corrs < 1.0)]
-
- if len(strong_corrs) > 0:
- report += "强相关性 (|r| > 0.7):\n\n"
- for idx, val in strong_corrs.items():
- report += f"- {idx[0]} 和 {idx[1]}: {val:.2f}\n"
- report += "\n"
- else:
- report += "没有发现强相关性 (|r| > 0.7)。\n\n"
-
- return report
- # 生成报告
- report = generate_data_report(df, "员工数据分析报告")
- print(report)
- # 保存报告到文件
- with open("data_analysis_report.md", "w", encoding="utf-8") as f:
- f.write(report)
复制代码
3. 结合其他Pandas函数使用
将describe()与其他Pandas函数结合使用,可以创建更强大的分析流程:
- # 创建一个综合分析函数
- def comprehensive_analysis(df):
- """执行全面的数据分析"""
- results = {}
-
- # 1. 基本描述性统计
- results['descriptive_stats'] = df.describe()
-
- # 2. 缺失值分析
- results['missing_values'] = missing_value_analysis(df)
-
- # 3. 分布分析
- numeric_cols = df.select_dtypes(include=[np.number]).columns
- if len(numeric_cols) > 0:
- results['distribution_analysis'] = distribution_analysis(df[numeric_cols])
-
- # 4. 相关性分析
- if len(numeric_cols) > 1:
- corr_matrix = df[numeric_cols].corr()
- results['correlation_matrix'] = corr_matrix
-
- # 找出强相关
- strong_corrs = corr_matrix.abs().stack().sort_values(ascending=False)
- strong_corrs = strong_corrs[(strong_corrs > 0.7) & (strong_corrs < 1.0)]
- results['strong_correlations'] = strong_corrs
-
- # 5. 异常值检测
- if len(numeric_cols) > 0:
- Q1 = df[numeric_cols].quantile(0.25)
- Q3 = df[numeric_cols].quantile(0.75)
- IQR = Q3 - Q1
-
- lower_bound = Q1 - 1.5 * IQR
- upper_bound = Q3 + 1.5 * IQR
-
- outliers = ((df[numeric_cols] < lower_bound) | (df[numeric_cols] > upper_bound)).sum()
- results['outliers'] = outliers
-
- # 6. 分类变量分析
- categorical_cols = df.select_dtypes(include=['object', 'category']).columns
- if len(categorical_cols) > 0:
- categorical_stats = {}
- for col in categorical_cols:
- categorical_stats[col] = {
- 'value_counts': df[col].value_counts(),
- 'percentages': df[col].value_counts(normalize=True) * 100
- }
- results['categorical_analysis'] = categorical_stats
-
- return results
- # 执行综合分析
- analysis = comprehensive_analysis(df)
- # 打印部分结果
- print("异常值数量:")
- print(analysis['outliers'])
- print("\n分类变量分析 - 部门:")
- print("计数:")
- print(analysis['categorical_analysis']['Department']['value_counts'])
- print("\n百分比:")
- print(analysis['categorical_analysis']['Department']['percentages'])
复制代码
4. 创建自定义描述函数
根据特定需求创建自定义描述函数,可以进一步提高分析效率:
- def custom_describe(df, group_by=None, numeric_only=True):
- """自定义描述函数,支持分组分析"""
-
- def describe_group(group):
- desc = group.describe()
-
- # 添加额外统计量
- desc.loc['range'] = desc.loc['max'] - desc.loc['min']
- desc.loc['variance'] = group.var()
- desc.loc['skewness'] = group.skew()
- desc.loc['kurtosis'] = group.kurtosis()
-
- # 添加变异系数
- desc.loc['cv'] = desc.loc['std'] / desc.loc['mean']
-
- return desc
-
- if group_by is not None:
- if numeric_only:
- numeric_cols = df.select_dtypes(include=[np.number]).columns
- df = df[[group_by] + list(numeric_cols)]
-
- grouped = df.groupby(group_by)
- result = grouped.apply(describe_group)
- return result
- else:
- if numeric_only:
- df = df.select_dtypes(include=[np.number])
- return describe_group(df)
- # 使用自定义描述函数
- print("按部门的自定义描述性统计:")
- print(custom_describe(df, group_by='Department'))
- print("\n整体自定义描述性统计:")
- print(custom_describe(df))
复制代码
总结
Pandas的describe()函数是数据分析师工具箱中不可或缺的工具,它能够快速提供数据集的关键统计特征。通过本文的介绍,我们不仅了解了describe()的基本用法,还探索了多种高级技巧,包括自定义百分位数、处理缺失值、分组分析、结果可视化等。
要充分利用describe()函数提升数据分析效率,建议:
1. 结合业务理解数据:统计指标只是数字,真正的洞察来自于将这些数字与业务背景相结合。
2. 创建可重用的分析函数:将常用的分析流程封装成函数,可以大大提高工作效率。
3. 可视化结果:将统计结果可视化,能够更直观地发现数据中的模式和异常。
4. 自动化报告生成:将分析过程自动化,生成标准化的报告,节省时间并确保一致性。
5. 持续学习:Pandas库不断发展,定期查看新功能和更新,可能会发现更高效的数据分析方法。
结合业务理解数据:统计指标只是数字,真正的洞察来自于将这些数字与业务背景相结合。
创建可重用的分析函数:将常用的分析流程封装成函数,可以大大提高工作效率。
可视化结果:将统计结果可视化,能够更直观地发现数据中的模式和异常。
自动化报告生成:将分析过程自动化,生成标准化的报告,节省时间并确保一致性。
持续学习:Pandas库不断发展,定期查看新功能和更新,可能会发现更高效的数据分析方法。
通过掌握这些技巧,你将能够更高效地使用Pandas进行数据探索和分析,快速洞察数据集的关键特征,为数据驱动的决策提供有力支持。 |
|