如何用Polars识别问卷数据中缺失的答案编码?
更符合Polars风格的问卷答案缺失项检查方案
问题背景
我有一个存储问卷问题答案编码的Polars DataFrame,想要确认所有预期答案是否都存在于该DataFrame中,若存在缺失则找出具体的缺失项。我已经写出了可行代码,但想了解有没有更符合Polars风格的实现方式?
原实现代码
import polars as pl fields = {} fields['q1'] = [f'Q1A{i}' for i in range(1,12)] fields['q2'] = [f'Q2A{i}' for i in range(1,3)] fields['q3'] = [f'Q3A{i}' for i in range(1,8)] fields['q4'] = [f'Q4A{i}' for i in range(1,4)] df = pl.DataFrame({'id': [1,2,3,4,5], 'q1': ['Q1A1,Q1A2','Q1A6','Q1A7,Q1A9','Q1A11','Q1A5,Q1A3'], 'q2': ['Q2A1','','Q2A2','Q2A1','Q2A1'], 'q3': ['Q3A1','Q3A3','Q3A2,Q3A5','Q3A6','Q3A7'], 'q4': ['Q4A1,Q4A3','Q4A1','','Q4A1','Q4A1'], }) for f in df.columns: if f.startswith('q'): print(pl.DataFrame(fields[f], schema={f: pl.String}) .join(df.select(pl.col(f).str.split(by=",").explode().unique().str.replace(r'(\: .*)','')) .filter(pl.col(f) != pl.lit('')), on = f, how = 'anti' ) .select(pl.lit(f), pl.len(), pl.col(f).str.join(', ').alias('missing') ) .rows() )
原运行结果
[('q1', 3, 'Q1A4, Q1A8, Q1A10')] [('q2', 0, '')] [('q3', 1, 'Q3A4')] [('q4', 1, 'Q4A2')]
优化后的Polars风格实现
下面的实现完全利用Polars的向量化、批量处理特性,避免Python循环,代码更简洁规整,也更符合Polars的设计理念:
import polars as pl # 定义预期答案映射 fields = { 'q1': [f'Q1A{i}' for i in range(1,12)], 'q2': [f'Q2A{i}' for i in range(1,3)], 'q3': [f'Q3A{i}' for i in range(1,8)], 'q4': [f'Q4A{i}' for i in range(1,4)] } # 将预期答案转换为结构化DataFrame,统一管理问题和对应答案 expected_df = pl.concat( [pl.DataFrame({'question': q, 'answer': ans}) for q, ans in fields.items()] ) # 处理原始数据:拆分多值答案、去重、过滤空值,转长表格式 existing_answers = df.select( pl.col('^q.*$').str.split(',').explode().unique() ).melt( variable_name='question', value_name='answer' ).filter(pl.col('answer') != '') # 通过anti join找出所有缺失的答案,按问题聚合统计结果 missing_df = expected_df.join( existing_answers, on=['question', 'answer'], how='anti' ).group_by('question').agg( pl.len().alias('missing_count'), pl.col('answer').str.join(', ').alias('missing_items') ).sort('question') # 左连接填充无缺失的问题,保证结果包含所有预期问题 final_result = pl.DataFrame({'question': list(fields.keys())}).join( missing_df, on='question', how='left' ).fill_null({'missing_count': 0, 'missing_items': ''}) print(final_result)
优化后运行结果
shape: (4, 3) ┌──────────┬──────────────┬──────────────────────┐ │ question ┆ missing_count ┆ missing_items │ │ --- ┆ --- ┆ --- │ │ str ┆ i64 ┆ str │ ╞══════════╪══════════════╪══════════════════════╡ │ q1 ┆ 3 ┆ Q1A4, Q1A8, Q1A10 │ │ q2 ┆ 0 ┆ │ │ q3 ┆ 1 ┆ Q3A4 │ │ q4 ┆ 1 ┆ Q4A2 │ └──────────┴──────────────┴──────────────────────┘
优化说明
- 去掉Python循环:全程用Polars内置操作处理,充分发挥Polars的向量化计算优势,性能更优
- 结构化管理预期答案:将预期答案转换为DataFrame,统一处理所有问题,代码扩展性更强
- 长表格式适配:用
melt将宽表转长表,简化后续的join和聚合逻辑,符合Polars的结构化数据处理思路 - 结果规整性:通过左连接填充无缺失的问题,确保结果包含所有预期问题,输出格式更统一
内容的提问来源于stack exchange,提问作者lmocsi
相关产品推荐
相关产品推荐

