简介:这是一份面向IT行业数据分析、市场调研及用户体验等场景的问卷调查模拟数据集,压缩包内包含1388个文件,约19.2MB,涵盖gif、js、tpl、mod、class、png、jsp、css等主要类型,其中js、css、html用于前端问卷展示与交互,class、jar、jsp对应后端服务逻辑,brz、flw、st等可能是表单流程或模板文件,整体呈现出完整Web问卷调查系统的结构。资源适合需要练习问卷设计、数据清洗、统计分析与可视化流程的初学者或从业者,可用于验证描述性统计、相关性检验及回归建模等方法。目前已有1371人学习下载,文件内还伴有sql、db等数据库文件及docx说明文档,便于了解问卷数据存储与导出方式,同时也展示了RAR压缩、分卷与密码保护等文件管理知识。借助这份模拟数据,读者能获得从数据采集到分析展示的完整实践素材。 先说一个很实际的场景:你负责维护一个在线问卷系统,或者正在做一份用户满意度统计分析,数据录入接口写好了、评分规则也调好了,但前端页面还是空荡荡的——因为真正的调研数据还在第三方平台上,没有接口,没有导出,一份都拿不到。这时候最需要的就是一份“问卷调查模拟数据”,塞进去把流程跑通、把看板填满、把统计代码验证掉。我手上的这份“问卷调查模拟数据2.rar”,就是干这个用的。
说实话,最开始我也没把这当回事,第1版是手工攒出来的200条数据,撑过了一轮功能演示,可一到回归测试就被戳穿了:逻辑矛盾、分布怪异、缺失值处理逻辑根本没触发。后来狠下心重写了一套生成方案,把问卷结构、量表逻辑、随机分布、缺失值注入全部脚本化,才有了这个2.0版本。这篇主要把这套思路拆开讲清楚:问卷数据结构应该怎么设计、数据生成脚本怎么写、打包交付时要注意什么,以及数据做完之后如何自检。不管你是做问卷系统开发、数据分析练习,还是课程作业里的模拟研究,这套方法都能直接用。
1. 一份"假"的问卷数据,为什么会成为项目里的硬需求
很多没做过数据处理的人会想:模拟数据不就是随便编几行Excel吗?实际上,问卷模拟数据的“像真程度”直接决定你后续流程能不能被真正验证。比如你写了一段计算满意度均分的代码,手工编的数据只有10条,均值一道就对了,但真实场景里会出现几百条记录、上百个字段,还有不少异常值——代码一跑就崩,或输出结果明显不对。这时候你才意识到,模拟数据的目的不是“看起来像数据”,而是让程序、看板、统计流程在正式数据到达之前,把所有坑都先踩一遍。
我归结下来,模拟数据在项目里至少解决四类需求:
- 系统开发侧:问卷创建、修改、发布、回收、导出全流程需要数据支撑,尤其是列表分页、图表联动、导出Excel这些依赖数据量的功能,没有数据根本看不出问题。
- 统计分析侧:信度分析、效度分析、均值方差计算、相关回归都需要完整的数据集,用模拟数据可以先跑通分析脚本,再等真数据替换。
- 演示与培训侧:给客户或领导看系统效果时,用真实用户数据有隐私风险,用模拟数据最稳妥,还能按需编排出“理想结果”和“异常情况”两种场景。
- 教学练习侧:学生学SPSS、R语言时必须有数据集,模拟数据能覆盖不同题型、不同量纲、不同缺失形态,比一上来就丢真实数据更适合练手。
再说说“2”这个版本号。第1版我在Excel里手工造数据,边编边复制的后果就是:有一道反向计分题和总分完全对不上,还有一批记录的提交时间在凌晨3点、作答时长却显示10秒——明显不合理。2.0版全部改成脚本生成,每次运行都能复现同一份结果,也可以改变随机种子生成新的样本,这才是真正的“模拟数据工程化”。如果你的项目里也需要频繁制造数据集,我强烈建议直接照这个思路走,能省掉无数返工时间。
2. 动手生成之前,先把问卷结构和量表逻辑画出来
模拟数据不是凭空捏造一堆列名,它必须对应一份真实的问卷。我在做这一版时,以“在线课程满意度调查”为原型,这样既有通用性,又能覆盖大多数问卷设计的典型字段。先不急着写代码,把问卷里出现的所有题项、选项取值、跳转逻辑、开放题都列成一张表,这是整个数据生成的“图纸”。
2.1 字段清单:能想到的都先列出来
我习惯把字段分成四类:基本信息、核心量表、行为类问题、系统记录字段。
| 字段名 | 字段含义 | 类型 | 取值范围/说明 |
|---|---|---|---|
| id | 记录编号 | 数值 | 主键,按顺序递增 |
| gender | 性别 | 单选题 | 1男 2女 3保密 |
| age_group | 年龄段 | 单选题 | 1=18岁以下 2=18-25 3=26-30 4=31-40 5=40以上 |
| education | 学历 | 单选题 | 1高中及以下 2大专 3本科 4硕士及以上 |
| city_level | 城市层级 | 单选题 | 1一线 2新一线 3二三线 4县及以下 |
| q1_course_satisfaction | 课程内容满意度 | 五级量表 | 1非常不满意 到 5非常满意 |
| q2_teacher_quality | 讲师水平评价 | 五级量表 | 1非常不满意 到 5非常满意 |
| q3_interaction | 互动环节感受 | 五级量表 | 1非常不满意 到 5非常满意 |
| q4_platform_stability | 平台稳定性评价 | 五级量表 | 1非常不满意 到 5非常满意 |
| q5_willing_to_recommend | 推荐意愿 | 五级量表 | 1非常不愿意 到 5非常愿意 |
| q6_reverse_item | 课程节奏混乱(反向题) | 五级量表 | 反向计分用 |
| attention_check | 陷阱题 | 单选题 | 请选择“比较同意” |
| purchase_intention | 续费意向 | 单选题 | 1非常不愿意…5非常愿意 |
| completition_time | 提交时间 | 日期时间 | 取近30天某个时间点 |
| duration_seconds | 作答时长 | 数值 | 约180到900秒之间 |
| source_channel | 来源渠道 | 单选题 | 1微信 2朋友圈 3短信 4其他 |
| open_comment | 开放建议 | 文本 | 部分为空,部分填充 |
这张表做好后,你就能清楚地知道每一列应该怎么生成,不会再出现生成完才想起来漏了某个字段的尴尬。
2.2 量表逻辑和维度分层
这里有个很关键的点:高质量模拟数据的核心不只是“每道题随机选个选项”,而是题目之间要有内在联系。比如真实场景里,课程满意度高的人,通常推荐意愿也高,续费意向也不低。如果你无视这种相关性,让每道题独立随机,那最后做出来的量表信度(Cronbach‘s α)会低得离谱,一眼就能看出是假数据。
所以我习惯把核心题目分成两个维度:
- 体验维度:q1、q2、q3、q4,反映对课程、讲师、互动、平台的整体体验;
- 意愿维度:q5、q6、purchase_intention,反映用户是否愿意继续学、推荐给朋友。
真实数据里这两个维度是正相关的,我生成时会用一个“潜在综合分”作为底层变量。具体做法:先生成一个连续变量 latent_score,范围大致在 -1 到 1 之间,然后各道题的概率分布都受它影响。latent_score 高的人,答正向题时更倾向于选4、5,答反向题时更倾向于选1、2。这样跑出来的信度系数一般能在0.7到0.9之间,观感非常真实。
3. 编写生成脚本:分布控制、反向计分和缺失值注入
图纸画好,下面进入正题。我用的是Python,配合random和pandas两个库就够了,不需要额外装重量级依赖。pandas负责整理成表格并导出CSV,random负责生成带权重的随机值。整个过程控制好随机种子之后,每次跑出来的数据完全一致,方便复现和调试。
3.1 基础框架与随机种子
先生成一条样本的底层框架。我在脚本开头固定随机种子,这样无论谁拿到这份脚本,跑出来的都是同一批数据,逻辑问题好排查。
import random import numpy as np import pandas as pd # 随机种子,保证每次生成的数据一致 random.seed(20240512) np.random.seed(20240512) population = 1200 # 目标样本量 def weighted_choice(options, weights): """按权重返回一个选项""" return random.choices(options, weights=weights, k=1)[0]人口学变量不能全等概率,一定要贴近真实人群分布。比如在线课程用户年龄段集中在18到35岁,学历以大专和本科居多,城市层级二线和三线占比较大。我通常会先构造一份“基准分布表”,生成时按这个表取数:
age_groups = [1, 2, 3, 4, 5] age_weights = [5, 25, 35, 25, 10] # 年龄段占比不平衡 genders = [1, 2, 3] gender_weights = [45, 50, 5] # 男45% 女50% 保密5% educations = [1, 2, 3, 4] education_weights = [10, 35, 40, 15] city_levels = [1, 2, 3, 4] city_weights = [20, 25, 40, 15]这一步很有讲究:如果每个变量的分布太平均,看一眼频次表就会觉得不真实;按贴近现实的偏态分布生成,后面做描述统计时,均值、标准差、性别比例都更接近一份实际调研报告。
3.2 核心变量的“潜在综合分”思路
关于潜在综合分,代码上是这样实现的。我先为每个人生成一个 latent_score,范围是0到1,然后把它映射到每道正向题的可能答案概率上:
def generate_core_scores(latent): # latent 越高,正向题越容易得4或5 if latent > 0.7: return [4, 5, 5, 5, 4] # 五个选项的常见结果 elif latent > 0.4: return [3, 4, 4, 4, 3] elif latent > 0.2: return [2, 3, 3, 3, 2] else: return [2, 2, 2, 2, 2]当然这个映射只是示意,实际代码里我会在 [1,5] 之间直接按 latent 计算多项分布的权重,保证答案不会全是整整齐齐的一种。重点在于,这套生成方式天然让同一维度下的题目呈正相关。之后再算Cronbach’s α,结果通常是可用的;你真拿去跑验证性因子分析,变量之间的相关矩阵也不会是“所有相关系数都接近0”的假死状态。
3.3 反向计分题和陷阱题
反向计分题是问卷设计里最常见的“区分认真作答用户”的手段。真实数据里,总有一部分人没耐心或乱填,反向题和正向题得分会逻辑冲突。我生成时会有两套路径:
- 绝大部分人(约85%)是“认真作答”的,他们正向题得4分,反向题给1或2分,总分加总后自然合理。
- 少部分人(约15%)是“随意作答”的,选项随机,正向和反向可能同时选高分,这时信度会被拉低一点,但整体不至于崩塌。
再就是陷阱题,例如“本题请选择比较同意”。脚本里直接生成对应选项,让数据里出现一批“合格”的注意力校验标记。后续分析时,可以直接按这个字段筛掉乱答用户,正好验证一遍数据清洗流程是否可靠。
# 注意力校验:约90%的人按提示作答,10%的人打错 def generate_attention_check(is_attentive): if is_attentive: return 4 # 比较同意 else: return random.randint(1, 5)3.4 缺失值与作答时长的合理注入
真实问卷数据永远有缺失。有的是用户跳过题不答,有的是中途放弃,有的是开放题留空。直接生成完整数据再导出,看着反而不真实。我在生成时会注入三种缺失形态:
- 随机缺失:每道题约1%到2%的概率留空。
- 尾部缺失:部分记录里,最后几题开放建议和推荐意愿为空,模拟用户答到后面没耐心了。
- 整块缺失:少量记录只有基本信息,核心量表全为空,模拟用户看了两题就退出。
作答时长也值得做假。不能所有样本都是600秒,我按正态分布生成,均值420秒,标准差150秒,再配合“作答越快、漏题越多”的规律,让时长和缺失率形成弱负相关,这样看起来更符合直觉:
duration = max(60, int(random.gauss(420, 150))) missing_probability = 0.01 if duration < 200: missing_probability = 0.04 elif duration < 300: missing_probability = 0.02最终把所有这些字段拼成一行,循环生成1200条,用pandas导出CSV,一份基础的“问卷调查模拟数据”就出来了。
4. 文件打包与交付:目录结构、编码规范和数据字典
数据生成完成后,重点就是交付环节。这里“2.rar”这个文件名里包含的其实是一套完整交付包,而不仅仅是数据文件本身。如果只丢一个CSV出去,使用方看不懂字段含义、不知道缺失值用什么表示,整个数据价值就大打折扣。
4.1 交付包里的标准目录
我这一版打包目录是这样的:
- data/
- raw_data.csv,清洗前模拟数据
- clean_data.csv,清洗后模拟数据
- docs/
- 数据字典.md
- 模拟数据说明.md
- scripts/
- generate_data.py
- check_data.py
用户拿到压缩包后,第一件事不是打开CSV,而是读数据字典,知道每个字段的取值、类型、缺失表示方式。脚本源码也放进去,是为了让懂技术的人能根据自己需要调整样本量、分布、随机种子。
4.2 CSV的编码和分隔符
这个问题不大但很坑。直接用pandas的to_csv导出,默认是UTF-8编码,在Windows上双击用Excel打开,中文十有八九乱码。我后来统一改成UTF-8 with BOM编码,Excel能正常识别,Python处理时用utf-8-sig也能读。分隔符建议用英文逗号,如果某列开放建议里有逗号,就用双引号包住,所有主流工具都能正常处理。
df.to_csv("raw_data.csv", index=False, encoding="utf-8-sig")4.3 数据字典怎么写
数据字典不需要花哨,但必须说清楚几件事:字段名、中文含义、数据类型、取值范围、缺失值标记、备注。我在文档里特别加了“生成逻辑”一列,例如“q6为反向计分,分析时需先反转再计算总分”“attention_check 为陷阱题,建议在清洗时过滤掉答错的样本”。这些备注对后续使用数据的人极其友好,尤其是同学或同事拿去写报告时,基本不用再反复问你字段是1还是2代表男。
4.4 为什么压缩包用 rar 而不是 zip
这个问题值得提一下。并不是因为rar比zip高级多少,而是我最终要在网盘或邮件里传输这份数据,rar格式自带恢复记录,文件完整性更有保证,尤其在网络传输不稳定的情况下能少掉很多麻烦。另外rar对重复文本的压缩率通常比zip略高,这份数据里大量重复的“非常满意”“比较满意”词汇,压缩下来体积差异还是能看到的。如果你接收方对rar不熟悉,也可以改发zip,但完整性校验和注释信息就要另想办法。
5. 数据生成后必须走完的三轮自检
生成数据不是跑完脚本就完工了。交出去之前,至少要过三轮自检,把最明显的数据坑都填掉。我自己第1版就是缺了这个环节,才被测试同事当场打脸。
5.1 第一轮:逻辑一致性校验
第一步先用脚本扫一遍:
- 年龄18岁以下的样本,学历不可能出现“硕士及以上”;
- 陷阱题选了“比较同意”的样本数量应为设定的90%左右;
- 反向题与正向题同时给高分的样本占比应在15%上下;
- 作答时长极短但完整作答全部题目的记录不多。
这些检查可以写成一个check_data.py,跑完直接输出异常记录数。我一般要求异常记录不超过总样本量的10%,如果超过,要么调整随机权重,要么检查代码里的逻辑冲突。
# 示例:逻辑校验 invalid = df[(df["age_group"] == 1) & (df["education"] == 4)] print("18岁以下但学历为硕士及以上的记录数:", len(invalid))5.2 第二轮:描述统计合理性
第二步算每个关键变量的频数、均值、标准差。拿年龄、性别、学历来说,分布应该贴近预设权重;拿量表总分来说,均值落在中间偏上,标准差保持在一定范围。
我还会顺手算一下核心量表的Cronbach’s α。如果你生成的数据α值低于0.6,那说明题目之间的相关结构太弱,后面演示信度分析时会显得很假;如果α值高到0.98,也不真实。通常0.7到0.9之间比较理想。这可以通过调节“认真作答”比例和latent_score对选项的影响强度来控制。
5.3 第三轮:敏感字段与可识别性检查
这是容易被忽略但非常重要的一步。模拟数据虽然都是编出来的,但也要做“脱敏”自检:确保不存在真实姓名、手机号、身份证号、邮箱等个人识别信息;开放建议字段里的文字不能是网上抄来的一段真实用户评价;ID也不要设置成纯递增整数,否则一眼就能看出来是生成数据。我一般把ID做成乱序整数,比如从10001开始的随机排列,看起来更像真实数据库里的主键。
6. 拿到这份模拟数据之后,还能往哪些方向扩展
生成完一份像样的模拟数据,你的工作没有到此为止。这套脚本往后的扩展方向很多,我这里分享两个最常见的。
第一个方向是增加时间序列维度。比如在提交时间字段上,按真实问卷回收规律给周中和周末设置不同流量,再往明细表里加入“问卷投放批次”“推广渠道”等字段,就可以用这份数据做渠道转化分析和投放效果对比。我后来在另一个项目里就做过类似处理,效果很好。
第二个方向是制作多份“同构不同源”的数据集。比如随机种子分别设为1、2、3,跑出三份结构完全一致但数值不同的数据,一份用来开发、一份用来测试、一份用来验收,避免开发人员和测试人员盯着同一份数据产生思维定式。只要脚本封装得好,每个版本只需要改个种子号就能重新出包,“问卷调查模拟数据2.rar”后面跟着出现3、4、5也就顺理成章了。
最后提醒一句:无论这份模拟数据做得再像,也只是测试和练习用的“替身”。正式发布或者写报告时,一定记得用真实调研数据替换,并在文档里注明哪些结论基于模拟数据、哪些基于真实数据——这一点我吃过亏,也希望大家不要踩同样的坑。
本文还有配套的精品资源,点击获取