使用pandas to_csv保存文件时提示目录不存在的问题求助
解决pandas to_csv保存GBIF数据时的路径错误问题
问题概述
处理GBIF数据时,读取C:\myfiles\flies_and_moths\occurrence_files目录下的CSV文件,处理后尝试保存到同一目录,持续报错“无法保存到不存在的目录”。已确认目标目录存在、可正常读取文件,处理后的DataFrame结构正常,但错误信息显示路径包含字典结构内容。
错误根源
核心问题出在species.name_lookup(taxonKey=taxon_key2)的返回值:该方法返回的是完整的GBIF响应字典,而非直接的物种名字符串。直接将字典用于拼接文件名时,字典的字符串表示(如{'offset': 0, 'limit': 100, ...})会被插入到路径中,系统会误将这部分当作子目录,而该“子目录”实际不存在,因此触发保存错误。
解决方案
需要从name_lookup返回的字典中提取合法的物种名称字段,并处理文件名中的非法字符:
- 从响应字典的
results列表中提取第一个结果的scientificName(物种学名); - 处理无结果返回的异常情况,避免程序崩溃;
- 替换文件名中的非法字符(如
/\:*?"<>|),确保路径合法。
关键代码修改
将原代码中获取物种名称的部分替换为:
# 调用GBIF API获取物种信息 gbif_response = species.name_lookup(taxonKey=taxon_key2) # 提取合法的物种名称 if gbif_response.get('results'): species_name2 = gbif_response['results'][0]['scientificName'] # 替换文件名中的非法字符,避免路径错误 invalid_chars = ['/', '\\', ':', '*', '?', '"', '<', '>', '|'] for char in invalid_chars: species_name2 = species_name2.replace(char, '_') else: # 无结果时用taxonKey作为文件名,避免空值 species_name2 = f"unknown_species_{taxon_key2}"
另外,原代码中assessors_name变量未定义,需要提前赋值(如assessors_name = "Your Name"),否则会触发NameError。
修改后的完整代码
import pygbif import os import numpy as np import pandas as pd my_dir = "C:/myfiles/flies_and_moths" os.chdir(my_dir) cwd = os.getcwd() new_folder = "occurrence_files" extract_to_directory = os.path.join(cwd, new_folder) # 定义assessors_name变量 assessors_name = "Your Name" for csv_file in os.listdir(extract_to_directory): try: full_path = os.path.join(extract_to_directory, csv_file) # 读取CSV文件到DataFrame df = pd.read_csv(full_path, sep='\t', low_memory= False) taxon_key2 = df['taxonKey'].iloc[0] # 修复:正确提取物种名称 gbif_response = species.name_lookup(taxonKey=taxon_key2) if gbif_response.get('results'): species_name2 = gbif_response['results'][0]['scientificName'] # 替换文件名非法字符 invalid_chars = ['/', '\\', ':', '*', '?', '"', '<', '>', '|'] for char in invalid_chars: species_name2 = species_name2.replace(char, '_') else: species_name2 = f"unknown_species_{taxon_key2}" # 修改DataFrame字段 df.loc[:, "catalogNumber"] = df["catalogNumber"].astype(str) df.loc[:, "CATALOG_NO"] = df["institutionCode"] + df["catalogNumber"] conditions = [ df['establishmentMeans'].isin(['INTRODUCED', 'INVASIVE', 'MANAGED', 'NATURALISED']), df['establishmentMeans'] == 'NATIVE', df['establishmentMeans'] == 'UNCERTAIN' ] values = ['3', '1', '5'] df.loc[:, "ORIGIN"] = np.select(conditions, values, default = "1") keeps = ['decimalLatitude', 'decimalLongitude', 'basisOfRecord','year','CATALOG_NO', 'ORIGIN'] # 筛选指定列 df2 = df.loc[:, keeps] df2["SPATIAL_REF"] ="WGS84" df2["YEAR"] = "2024" df2["CITATION"] = "GBIF 2024" df2["PRESENCE"] = "1" df2["BINOMIAL"] = species_name2 df2["SEASONAL"] = "1" df2["COMPILER"] = assessors_name # 重命名列 df2.rename(columns={"decimalLatitude": "DEC_LAT","decimalLongitude": "DEC_LONG","basisOfRecord": "BasisOfRec","year": "EVENT_YEAR"}, inplace=True) # 保存CSV outname =f'{species_name2}.csv' fullname = os.path.join(extract_to_directory, outname) df2.to_csv(fullname, index=False) # 添加index=False避免保存索引列 except Exception as e: print(f"did not write new file: {e}")
额外说明
- 添加
index=False到to_csv方法,避免将DataFrame的索引列保存到CSV中(根据需求可调整); - 处理
assessors_name未定义的问题,确保程序正常运行; - 对无物种结果的情况做了兜底处理,避免因API返回空结果导致的报错。
内容的提问来源于stack exchange,提问作者noodle222
相关产品推荐
相关产品推荐

