如何从CSV文件生成按Rack分组的字典列表?
问题描述
现有如下结构的CSV文件,包含Rack、Tube、Well、sample_vol、solvent_vol列:
| Rack | Tube | Well | sample_vol | solvent_vol |
|---|---|---|---|---|
| 1 | 0 | A1 | 230 | 400 |
| 1 | 1 | B1 | 200 | 20 |
| 2 | 2 | G1 | 5 | 30 |
| 3 | 1 | A1 | 90 | 40 |
| 3 | 20 | A1 | 100 | 90 |
需求是:为每个不同的Rack值创建一个字典,字典以Tube为键、sample_vol为值,最终将这些字典整合到一个列表中,期望输出如下:
print(rack_list)
[{'0':230,'1':200},{'2':5},{'1':90,'20':100}]
注:原示例输出中第三个字典的20对应值应为100,此处修正了笔误
目前编写的Python代码卡在按Rack分组生成字典列表的步骤:
csv_reader = csv.DictReader(csvfile) header = csv_reader.fieldnames solvent_volume_map = {} sample_volume_map = {} max_rack = None rack = None rack_list = [] for csv_row in csv_reader: rack = int(csv_row["Rack"]) if max_rack == None or max_rack < rack: max_rack = rack destination_well = csv_row['Well'] source_tube = csv_row['Tube'] source_rack = csv_row['Rack'] print(source_rack) try: solvent_volume = float(csv_row['solvent_vol']) sample_volume = float(csv_row['sample_vol']) except ValueError as e: # blank csv entry solvent_volume = "skip" sample_volume = "skip" solvent_volume_map[destination_well] = solvent_volume for i in range(max_rack): sample_volume_map[source_tube] = sample_volume rack_list.append(sample_volume_map)
解决方案
原代码的问题在于未正确按Rack分组,且循环中重复添加同一个字典对象,导致结果不符合预期。以下是两种可行的实现方式:
方法一:普通字典分组
先按Rack编号分组存储每个Tube对应的sample_vol,最后按Rack顺序整理成列表:
import csv rack_dict = {} # 键为Rack编号,值为对应Tube-sample_vol的字典 with open('your_file.csv', 'r') as csvfile: csv_reader = csv.DictReader(csvfile) for row in csv_reader: rack_num = int(row["Rack"]) tube = row["Tube"] try: sample_vol = float(row["sample_vol"]) except ValueError: sample_vol = "skip" # 若当前Rack未在分组字典中,先创建空字典 if rack_num not in rack_dict: rack_dict[rack_num] = {} rack_dict[rack_num][tube] = sample_vol # 按Rack编号从小到大排序,提取对应字典组成目标列表 rack_list = [rack_dict[num] for num in sorted(rack_dict.keys())] print(rack_list)
方法二:使用itertools.groupby(需先按Rack排序)
groupby要求数据先按分组键排序,因此需先对CSV行按Rack字段排序:
import csv from itertools import groupby with open('your_file.csv', 'r') as csvfile: csv_reader = csv.DictReader(csvfile) # 按Rack字段排序,转换为整数确保排序逻辑正确 sorted_rows = sorted(csv_reader, key=lambda x: int(x["Rack"])) rack_list = [] # 按Rack分组处理 for rack_key, group in groupby(sorted_rows, key=lambda x: int(x["Rack"])): tube_map = {} for row in group: tube = row["Tube"] try: sample_vol = float(row["sample_vol"]) except ValueError: sample_vol = "skip" tube_map[tube] = sample_vol rack_list.append(tube_map) print(rack_list)
两种方法运行后都会输出符合预期的结果:
[{'0': 230.0, '1': 200.0}, {'2': 5.0}, {'1': 90.0, '20': 100.0}]
若需要整数类型的sample_vol,可将代码中的float替换为int,根据实际数据情况调整即可。
内容的提问来源于stack exchange,提问作者Devang Mehta
相关产品推荐
相关产品推荐

