如何将数据插入CSV指定列?插入第二列失败求助
问题解决:CSV数据写入列错位问题
问题说明
现有代码试图创建包含Date和Rotifer Count列的CSV文件,读取文件夹内文件日期并通过机器学习模型统计每日检测数,但存在两个问题:
- 第二批统计数据(Rotifer Count)无法写入第二列,始终追加到第一列的末尾
- 使用
columns([])指定列时触发KeyError
问题根源
- 代码将日期数据和计数数据分两次循环单独追加写入CSV,每次写入的都是单列数据,CSV的追加模式会默认将新数据放到下一行,而非指定列
- 两次循环的逻辑没有关联,无法保证日期和计数的行对应关系,导致数据完全错位
- 直接用
pd.DataFrame([单值])生成的是单列表格,写入时无法匹配已有的两列结构
修复方案
核心思路是先将日期和对应计数配对成完整的行数据,再统一写入CSV,避免分两次单独追加。具体步骤:
- 先收集所有日期数据和对应计数数据到同一个数据结构中
- 组装成符合列结构的DataFrame后一次性写入,或者逐行写入完整的两行数据
修改后的完整代码
import csv import os import datetime import pandas as pd from PIL import Image # 假设model已提前加载,current_frame已初始化 # 1. 初始化存储数据的列表,每个元素是[日期, 轮虫计数] data_rows = [] # 2. 处理日期数据,收集所有目标日期 org_images_path = fr"/wormbot/{lifespan_number}" file_prefix = "frame" img_list = sorted(os.listdir(org_images_path)) img_list = [img_name for img_name in img_list if img_name.startswith(file_prefix)] date_list = [] for index, img_name in enumerate(img_list): if index % 2 == 0: image_path = os.path.join(org_images_path, img_name) get_image = os.path.getmtime(image_path) date_number = datetime.datetime.fromtimestamp(get_image).day date_list.append(date_number) # 3. 处理计数数据,收集对应检测数 count_list = [] output_crop = "你的output_crop实际路径" # 替换为真实路径 for image in sorted(os.listdir(output_crop)): if image.endswith('.jpg'): image_path = os.path.join(output_crop, image) img = Image.open(image_path) results = model(img, conf=.19, verbose=False, max_det=5) counts = {} for result in results: boxes = result.boxes.cpu().numpy() for box in boxes: cls = int(box.cls[0]) counts[cls] = counts.get(cls, 0) + 1 # 简化计数逻辑,避免重复判断 # 用get方法直接获取对应类别计数,不存在则返回0,避免KeyError alive = str(counts.get(key, 0)) # key需根据模型实际类别调整,比如0代表存活轮虫 count_list.append(alive) current_frame += 1 img.close() # 4. 配对日期和计数,取两者较短长度避免索引越界 min_length = min(len(date_list), len(count_list)) for i in range(min_length): data_rows.append([date_list[i], count_list[i]]) # 5. 写入CSV文件 csv_path = fr"/home/lm/anaconda3/envs/yolov8_rotiferdetect/CSV_files/exp_{lifespan_number}.csv" with open(csv_path, 'w', newline='') as csvfile: filewriter = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) filewriter.writerow(['Date', 'Rotifer Count']) filewriter.writerows(data_rows) # 也可以用pandas简化写入: # df = pd.DataFrame(data_rows, columns=['Date', 'Rotifer Count']) # df.to_csv(csv_path, index=False)
关键优化点
- 用
counts.get(cls, 0)替代原有的判断逻辑,简化代码同时避免KeyError - 将日期和计数分别收集到列表后再配对,保证每行数据的完整性
- 一次性写入所有行数据,避免分多次追加导致的列错位问题
- 新增行数校验,避免因两个文件夹文件数量不一致导致的索引错误
内容的提问来源于stack exchange,提问作者Colton Pelletier
相关产品推荐
相关产品推荐

