在了解了表格数据的基本结构后,生成合成表格最直接的方法之一是逐列创建值,而不考虑其他列。这种方法称为独立列值生成。这里的核心假设是,在同一行中,一列的值不影响另一列的值。虽然这在真实数据集中通常不成立(比如年龄与收入、城市与邮政编码之间的关系),但这个简化假设使得生成过程更容易上手。工作原理假设您的表有几列,例如 Age、Department 和 Salary。使用独立列生成方法,您需要:决定如何为 Age 列生成合成值。决定如何为 Department 列生成合成值。决定如何为 Salary 列生成合成值。通过对每列独立应用这些规则来生成所需行数。为特定列生成值的方式通常取决于其数据类型(数值型、类别型等),并且通常涉及模仿原始数据中观察到的特征(如果可用)。独立生成数值列对于包含数字的列(如 Age、Height、Price),您通常可以使用上一章中介绍的统计分布。根据观察数据: 如果您有真实数据集,可以计算数值列的基本统计量,如最小值、最大值、均值($ \mu $)和标准差($ \sigma $)。然后,您可以从近似原始分布的分布中采样来生成合成值。例如:如果数据大致呈钟形,则从正态(高斯)分布中采样:$ \mathcal{N}(\mu, \sigma^2) $。如果数据在范围 $[a, b]$ 内均匀分布,则从均匀分布中采样:$ U(a, b) $。没有观察数据时: 如果您没有真实数据,您需要定义所需的属性。例如,您可以决定合成的 Age 值应在 18 到 65 之间均匀分布。假设我们想生成 100 个合成的 Age 值,根据观察,真实年龄大致呈正态分布,均值为 40,标准差为 12。我们可以使用一个函数(例如 Python 中的 numpy.random.normal)从 $ \mathcal{N}(40, 12^2) $ 中抽取 100 个点。import numpy as np # 基于观察数据的参数(示例) mean_age = 40 std_dev_age = 12 number_of_rows = 100 # 独立生成合成年龄 synthetic_ages = np.random.normal(loc=mean_age, scale=std_dev_age, size=number_of_rows) # 确保年龄符合实际(例如,非负,可能是整数) synthetic_ages = np.clip(synthetic_ages, 0, None) # 确保非负 synthetic_ages = synthetic_ages.astype(int) # 转换为整数年龄 # print(synthetic_ages[:10]) # 显示前 10 个生成的年龄我们可以使用直方图将生成的年龄分布与原始分布(如果可用)进行视觉比较。{"layout": {"title": "年龄分布:真实 vs. 合成(独立)", "xaxis": {"title": "年龄"}, "yaxis": {"title": "计数"}, "barmode": "overlay"}, "data": [{"type": "histogram", "x": [35, 42, 28, 55, 41, 39, 48, 33, 25, 60, 44, 37, 40, 51, 29], "name": "真实数据", "opacity": 0.75, "marker": {"color": "#4c6ef5"}}, {"type": "histogram", "x": [40, 52, 28, 45, 38, 39, 58, 33, 21, 62, 41, 35, 42, 50, 27, 43, 36, 48, 31, 55], "name": "合成数据", "opacity": 0.75, "marker": {"color": "#ff922b"}}]}真实数据小样本与基于统计属性独立列生成合成数据的年龄分布比较。合成数据旨在模仿整体形状。独立生成类别列对于包含文本或类别的列(如 Department、Product Type、City),一种常见做法是复制原始数据中观察到的频率分布。计算频率: 计算每个类别在真实数据列中出现的次数。计算每个类别的概率(或比例)。基于概率采样: 根据计算出的概率随机选择类别来生成合成值。例如,如果真实数据中的 Department 列有:销售:50%工程:30%市场:20%您将生成合成 Department 值,使其大致有 50% 是“销售”,30% 是“工程”,20% 是“市场”。import numpy as np # 观察到的频率(示例) departments = ['Sales', 'Engineering', 'Marketing'] probabilities = [0.5, 0.3, 0.2] number_of_rows = 100 # 独立生成合成部门 synthetic_departments = np.random.choice(departments, size=number_of_rows, p=probabilities) # print(synthetic_departments[:10]) # 显示前 10 个生成的部门柱状图有助于比较频率。{"layout": {"title": "部门频率:真实 vs. 合成(独立)", "xaxis": {"title": "部门"}, "yaxis": {"title": "频率 (%)"}, "barmode": "group"}, "data": [{"type": "bar", "x": ["Sales", "Engineering", "Marketing"], "y": [50, 30, 20], "name": "真实数据频率", "marker": {"color": "#4c6ef5"}}, {"type": "bar", "x": ["Sales", "Engineering", "Marketing"], "y": [48, 33, 19], "name": "合成数据频率", "marker": {"color": "#ff922b"}}]}真实数据比例与独立生成的样本之间的部门频率比较。合成频率近似于目标概率。独立生成方法的优点简便性: 这可以说是最容易理解和实现的方法。您只需一次考虑一列。速度: 独立生成列的计算成本较低,特别是对于大型数据集。隐私方面: 通过在生成每列值时不参考同一行中的其他列,您可以固有地打破原始数据中存在的任何统计关系。这可以作为匿名化的起点,尽管其本身通常不足。局限:独立性假设“主要缺点是独立性假设。数据很少有完全独立的列。”年龄与薪资: 年轻员工的薪资通常低于年龄更大、经验更丰富的人。独立生成可能会创建 20 岁却薪资很高,或 60 岁却拿着入门级薪资的记录。城市与州/邮政编码: 独立生成这些字段几乎肯定会导致不存在的组合(例如,'California' 中的 'Seattle')。医疗数据: 症状、诊断和治疗之间高度相关。独立生成可能会产生无意义的医疗记录。由于它忽略了这些关系,纯粹独立生成的数据通常缺乏实用性,对于依赖特征间关联的机器学习任务。仅根据此类数据训练的模型可能无法学到现实中存在的重要模式。总结独立列值生成是创建合成表格数据的一种主要方法。它涉及分别为每列生成数据,通常通过模仿原始数据中观察到的边际分布(如数字的均值/标准差,或类别的频率)。尽管简单快速,其核心局限在于未能捕捉列之间的关系,这可能降低生成数据集的真实性和有用性。这引导我们考虑那些试图保留一些列间关联的方法,我们将在接下来介绍。