如何在Pandas中从字典字符串列高效生成患者到访次数统计列(无预先患者名单)
优化Pandas中字符串化字典列表的患者到访次数统计方案
你的这个需求很常见——处理存储为字符串的嵌套字典列表,还要动态生成患者列来统计每个诊室的到访次数,同时避开低效的逐行迭代。先看了你的现有实现,功能没问题,但在大数据集上确实有优化空间,尤其是apply加逐行eval的重复开销会拖慢速度。下面给你几个更高效、更符合Pandas风格的优化方案:
一、先批量解析字符串,避免重复开销
首先,你的原始方案里每个患者列的统计都要重新eval一次行数据,这是很大的浪费。我们先一次性把所有字符串解析成结构化的列表:
import pandas as pd from collections import defaultdict # 批量解析visits列的字符串为Python列表 df['visits_parsed'] = df['visits'].apply(eval)
注:如果你的数据格式是标准JSON(比如键用双引号),用
json.loads替代eval会更安全;如果是Python字典格式的字符串,eval是最直接的方式。
二、方案1:用Pandas结构化展开+聚合(推荐,性能最优)
这个方案完全利用Pandas的内置向量化操作,把嵌套结构展开后做聚合统计,非常符合Pandas的设计思维:
# 1. 把每个诊室的访问列表拆成单独行,保留原索引 exploded = df.explode('visits_parsed').reset_index(names='original_index') # 2. 把每个字典展开成患者列 normalized = pd.json_normalize(exploded['visits_parsed']) # 3. 合并数据,把患者列转成行,统计每个诊室的到访次数 counts = exploded.join(normalized).melt( id_vars='original_index', var_name='patient', value_name='visit_date' ) # 过滤掉空值(对应患者没在该行出现的情况),再按诊室和患者分组计数 counts = counts.dropna(subset=['visit_date']).groupby( ['original_index', 'patient'] ).size().unstack(fill_value=0) # 4. 把统计结果合并回原DataFrame df_final = df.join(counts).drop('visits_parsed', axis=1)
这个方案的优势是全程用Pandas底层优化过的操作,没有自定义Python循环,大数据集下性能会比你的原始方案提升非常明显。
三、方案2:单次遍历批量统计(适合内存有限场景)
如果你的数据量极大,展开成多行可能占用过多内存,可以用一次遍历完成所有患者的统计,内存占用更低:
# 初始化嵌套字典,记录每个原行索引对应的患者计数 row_patient_counts = defaultdict(lambda: defaultdict(int)) # 只遍历一次所有解析后的访问数据 for row_idx, visits_list in df['visits_parsed'].items(): for visit_dict in visits_list: # 遍历当前访问记录里的患者 for patient_name in visit_dict: row_patient_counts[row_idx][patient_name] += 1 # 把统计结果转成DataFrame,合并回原表 count_df = pd.DataFrame.from_dict(row_patient_counts, orient='index').fillna(0).astype(int) df_final = df.join(count_df).drop('visits_parsed', axis=1)
这个方法只需要遍历一次所有访问记录,比你的原始方案(先遍历找患者,再逐患者遍历统计)减少了N次遍历(N是患者数量),效率提升很显著。
优化方案的核心优势
- 减少重复解析:只解析一次字符串,避免了原始方案中每个患者列都重新解析的开销
- 避免冗余遍历:最多遍历两次数据(解析+统计),而原始方案需要遍历1+N次(N为患者数)
- 利用Pandas内置优化:方案1用的
explode、json_normalize、groupby都是C级别的优化操作,比自定义Python循环快得多
另外,如果你后续有数据存储的控制权,建议尽量把这类嵌套数据存储为JSON格式或者结构化的列,这样解析和处理会更安全高效。
内容的提问来源于stack exchange,提问作者AJY
相关产品推荐
相关产品推荐

