Python案例如何用Pandas做数据分组洗牌

wen python案例 1

本文目录导读:

Python案例如何用Pandas做数据分组洗牌

  1. 方法1:使用groupby和sample
  2. 方法2:使用groupby和sample保持组结构
  3. 方法3:加权随机洗牌
  4. 方法4:保持行数平衡的分组洗牌
  5. 方法5:交叉验证的分组洗牌
  6. 实际应用示例

我来介绍几种使用Pandas进行数据分组洗牌的方法。

方法1:使用groupby和sample

import pandas as pd
import numpy as np
# 创建示例数据
df = pd.DataFrame({
    'group': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C'],
    'value': [1, 2, 3, 4, 5, 6, 7, 8]
})
print("原始数据:")
print(df)
# 方法1:在每个组内随机洗牌
def shuffle_group(group):
    return group.sample(frac=1, random_state=42)
shuffled_df = df.groupby('group', group_keys=False).apply(shuffle_group)
print("\n分组内洗牌结果:")
print(shuffled_df)

方法2:使用groupby和sample保持组结构

# 保持组内结构,只打乱组顺序
def shuffle_groups(df, group_col):
    """打乱组的顺序,但保持组内数据不变"""
    # 获取唯一组列表
    unique_groups = df[group_col].unique()
    # 随机打乱组顺序
    shuffled_groups = np.random.permutation(unique_groups)
    # 创建新的DataFrame
    result = pd.concat([df[df[group_col] == g] for g in shuffled_groups], ignore_index=True)
    return result
# 示例
df_shuffled_groups = shuffle_groups(df, 'group')
print("组顺序打乱结果:")
print(df_shuffled_groups)

方法3:加权随机洗牌

# 基于权重的组内洗牌
def weighted_shuffle(group, weight_col=None):
    """基于权重进行组内洗牌"""
    if weight_col:
        weights = group[weight_col]
        return group.sample(frac=1, weights=weights)
    return group.sample(frac=1)
# 创建带权重的数据
df_weight = pd.DataFrame({
    'group': ['A', 'A', 'A', 'B', 'B', 'B'],
    'value': [1, 2, 3, 4, 5, 6],
    'weight': [0.1, 0.2, 0.7, 0.3, 0.3, 0.4]
})
# 按权重洗牌
weighted_shuffled = df_weight.groupby('group', group_keys=False).apply(
    lambda x: weighted_shuffle(x, 'weight')
)
print("\n加权洗牌结果:")
print(weighted_shuffled)

方法4:保持行数平衡的分组洗牌

def balanced_group_shuffle(df, group_col, seed=None):
    """均衡的分组洗牌,确保每个组有相似的样本数"""
    if seed is not None:
        np.random.seed(seed)
    result_dfs = []
    groups = df.groupby(group_col)
    # 找到最小组的样本数
    min_size = groups.size().min()
    for name, group in groups:
        # 从每个组中随机选择相同数量的样本
        sampled = group.sample(n=min_size, random_state=seed)
        result_dfs.append(sampled)
    return pd.concat(result_dfs, ignore_index=True)
# 创建不均衡的数据
df_imbalanced = pd.DataFrame({
    'group': ['A', 'A', 'A', 'A', 'B', 'B', 'C', 'C', 'C'],
    'value': [1, 2, 3, 4, 5, 6, 7, 8, 9]
})
balanced = balanced_group_shuffle(df_imbalanced, 'group', seed=42)
print("\n均衡洗牌结果:")
print(balanced)

方法5:交叉验证的分组洗牌

def group_kfold_split(df, group_col, n_folds=5, shuffle=True, random_state=None):
    """分组K折交叉验证的数据分割"""
    from sklearn.model_selection import GroupKFold
    groups = df[group_col]
    gkf = GroupKFold(n_splits=n_folds)
    folds = []
    for train_idx, test_idx in gkf.split(df, groups=groups):
        train_df = df.iloc[train_idx]
        test_df = df.iloc[test_idx]
        folds.append((train_df, test_df))
    return folds
# 使用示例
df_large = pd.DataFrame({
    'group': ['A']*10 + ['B']*10 + ['C']*10,
    'feature1': np.random.randn(30),
    'feature2': np.random.randn(30),
    'target': np.random.randint(0, 2, 30)
})
folds = group_kfold_split(df_large, 'group', n_folds=3)
print("\n分组K折交叉验证:")
for i, (train, test) in enumerate(folds):
    print(f"Fold {i+1}: 训练集 {len(train)} 样本, 测试集 {len(test)} 样本")
    print(f"训练集分组: {train['group'].unique()}")
    print(f"测试集分组: {test['group'].unique()}")

实际应用示例

# 销售数据的分组分析
def analyze_sales_shuffle(sales_df):
    """对销售数据进行分组洗牌分析"""
    # 按地区分组洗牌
    shuffled_by_region = sales_df.groupby('region', group_keys=False).apply(
        lambda x: x.sample(frac=1)
    )
    # 计算洗牌前后的统计
    original_stats = sales_df.groupby('region')['sales'].agg(['mean', 'std'])
    shuffled_stats = shuffled_by_region.groupby('region')['sales'].agg(['mean', 'std'])
    # 比较差异
    comparison = pd.DataFrame({
        '原始均值': original_stats['mean'],
        '洗牌后均值': shuffled_stats['mean'],
        '差异': original_stats['mean'] - shuffled_stats['mean']
    })
    return comparison
# 示例数据
sales_data = pd.DataFrame({
    'region': ['North']*5 + ['South']*5 + ['East']*5,
    'product': ['A', 'B', 'C', 'D', 'E']*3,
    'sales': [100, 150, 200, 120, 180, 90, 130, 160, 110, 140, 80, 120, 170, 95, 155]
})
result = analyze_sales_shuffle(sales_data)
print("\n销售数据分析结果:")
print(result)

这些方法可以根据你的具体需求选择使用:

  • 方法1:组内完全随机化
  • 方法2:保持组结构,只打乱顺序
  • 方法3:带权重的随机化
  • 方法4:均衡采样
  • 方法5:交叉验证分割

选择哪种方法取决于你的具体应用场景和数据分析需求。

抱歉,评论功能暂时关闭!