如何为现有CSV文件新增Age列并根据DOB计算年龄?代码报错求助
问题描述
我有一个包含三列的CSV文件,列名分别为Name、DOB(格式为YYYY-MM-DD)、Salary,数据示例如下:
Name,DOB,Salary Sam,2000-01-05,23000 Tyson,1989-09-11,29000 Lara,2002-11-19,19000 Brian,1990-04-20,21000 Tessa,2000-08-17,15000
需求说明:读取该文件并在终端展示数据,同时计算出每个人的年龄,新增名为'Age'的列,输出示例如下:
Name,DOB,Salary,Age Sam,2000-01-05,23000,22 Tyson,1989-09-11,29000,51 Lara,2002-11-19,19000,20 Brian,1990-04-20,21000,32 Tessa,2000-08-17,15000,22
我编写了如下Python代码:
import csv import datetime def getage(now, dob): years = now.year - dob.year months = now.month - dob.month if now.day < dob.day: months -= 1 while months < 0: months += 12 years -= 1 return '%sy%smo' % (years, months) with open('emp_details.csv', 'r') as fin, open('emp_details_out.csv', 'w') as fout: csv_reader = csv.reader(fin) csv_writer = csv.writer(fout) for data in csv_reader: today = datetime.date.today() DOB = datetime.datetime.strptime(data["DOB"], "%Y-%m-%d").date() data["Age"] = getage(today, DOB) csv_writer.writerow(data)
但运行时出现如下错误:
DOB = datetime.datetime.strptime(data["DOB"], "%Y-%m-%d").date() TypeError: list indices must be integers or slices, not str
我是CSV处理新手,急需帮助解决该问题。
错误原因分析
你使用csv.reader读取文件时,返回的每一行数据是列表类型,只能通过整数索引(比如data[1])访问列值,无法用字符串键(比如data["DOB"])直接定位列。另外你的getage函数返回的是22y0mo这类格式,和需求中的整数年龄不符,也需要调整。
修正方案
方法1:使用csv.DictReader和csv.DictWriter(推荐)
这种方法会将每行数据转为字典,直接用列名访问值,更贴合你原本的代码逻辑:
import csv import datetime def calculate_age(now, dob): # 计算整数年龄,匹配需求示例格式 age = now.year - dob.year # 如果当前日期未到当年生日,年龄减1 if (now.month, now.day) < (dob.month, dob.day): age -= 1 return age with open('emp_details.csv', 'r') as fin, open('emp_details_out.csv', 'w', newline='') as fout: # 自动识别表头作为字典键 csv_reader = csv.DictReader(fin) # 定义输出列名,新增Age列 fieldnames = csv_reader.fieldnames + ['Age'] csv_writer = csv.DictWriter(fout, fieldnames=fieldnames) # 写入表头 csv_writer.writeheader() # 打印表头到终端 print(','.join(fieldnames)) today = datetime.date.today() for row in csv_reader: # 解析DOB为日期对象 dob = datetime.datetime.strptime(row['DOB'], "%Y-%m-%d").date() # 计算年龄并添加到字典 row['Age'] = calculate_age(today, dob) # 写入文件 csv_writer.writerow(row) # 在终端打印该行数据 print(','.join([str(row[field]) for field in fieldnames]))
方法2:继续使用csv.reader(列表索引方式)
如果坚持用csv.reader,需要手动处理表头和数据行的索引对应:
import csv import datetime def calculate_age(now, dob): age = now.year - dob.year if (now.month, now.day) < (dob.month, dob.day): age -= 1 return age with open('emp_details.csv', 'r') as fin, open('emp_details_out.csv', 'w', newline='') as fout: csv_reader = csv.reader(fin) csv_writer = csv.writer(fout) # 读取并处理表头 header = next(csv_reader) header.append('Age') csv_writer.writerow(header) print(','.join(header)) # 获取DOB列的索引位置 dob_index = header.index('DOB') today = datetime.date.today() for row in csv_reader: # 通过索引获取DOB值并解析 dob_str = row[dob_index] dob = datetime.datetime.strptime(dob_str, "%Y-%m-%d").date() age = calculate_age(today, dob) # 添加年龄到行数据 row.append(str(age)) # 写入文件并打印到终端 csv_writer.writerow(row) print(','.join(row))
内容的提问来源于stack exchange,提问作者Psyfer.Dev
相关产品推荐
相关产品推荐

