3、数据导入导出:CSV、Excel、数据库连接与操作

做药物知识图谱,数据来源五花八门。你拿到手的,可能是CSV表格、Excel报表,甚至是把数据库直接甩给你——“你自己连吧”。说白了,数据导入导出是R语言的第一道基本功。这一章,我带你过一遍最常见的三种数据源操作:CSV、Excel和数据库。每个坑我都踩过,你听我细说。

3.1 CSV文件:最通用的交换格式

CSV,逗号分隔值,说白了就是个文本文件。R自带的read.csv()和write.csv(),够用。但项目中我遇到过一个问题:药物名称里居然带逗号?比方说“阿司匹林,肠溶片”,一读进来就裂成两列,数据全乱了。

避坑:字段内包含逗号、换行符或双引号时,记得用quote = "\""包裹,或者用readr::read_csv()——这个包会自动处理。

我个人习惯用data.table::fread(),速度是原生的10倍以上。尤其是几百万行的药物注册数据,fread几乎秒读。写法很简单:

library(data.table)
drugs <- fread("drugbank.csv", encoding = "UTF-8")

导出也一样:

fwrite(drugs, "drugbank_clean.csv")
函数包速度适用场景
read.csv()base慢小文件、一次性
readr::read_csv()readr中等规范格式、带消息提示
data.table::fread()data.table快大文件、自动识别分隔符

3.2 Excel文件:别被格式坑了

医药行业,Excel用得特别多。你要小心:多个Sheet、合并单元格、日期格式、科学计数法……. 我之前接过一个项目,同事把药物ATC代码存成Excel,结果“123456789012”直接变“1.23E+11”,气得我连夜写了个转换脚本。

R里推荐两个包:readxl和openxlsx。前者只读不写,轻量;后者能读写,支持样式。上代码:

library(readxl)
sheets <- excel_sheets("drug_atc.xlsx")
sheet1 <- read_excel("drug_atc.xlsx", sheet = 1)
# 指定列类型,避免数字变字符
sheet2 <- read_excel("drug_atc.xlsx", sheet = "ATC", col_types = c("text", "text", "numeric"))
小技巧:用read_excel()时,参数guess_max可以设置前N行用于类型猜测。如果前100行全是数字,第101行突然出现“N/A”,就全列变字符。我一般设guess_max = 2000。

写Excel,我习惯用openxlsx:

library(openxlsx)
wb <- createWorkbook()
addWorksheet(wb, "drugs")
writeData(wb, "drugs", drugs_df)
saveWorkbook(wb, "drug_output.xlsx", overwrite = TRUE)

3.3 数据库连接:从R直连 SQL

药物知识图谱的数据,很多时候存在关系型数据库里。比如药品说明书、不良反应报告、临床试验数据。你要做的,是从R里建连接、写SQL、拿结果。

主流方案:DBI + 对应数据库驱动。我拿MySQL举例:

library(DBI)
library(RMySQL)

con <- dbConnect(
  MySQL(),
  host = "localhost",
  user = "root",
  password = "your_password",
  dbname = "drug_kg"
)

# 查询
result <- dbGetQuery(con, "SELECT * FROM drug_info WHERE atc_code LIKE 'A%'")
# 写入
dbWriteTable(con, "drug_filtered", result, overwrite = TRUE)
# 关闭
dbDisconnect(con)

还有odbc包,支持微软SQL Server、PostgreSQL。嗯,这个要提一句,如果你公司的数据库是SQL Server,用odbc连,驱动配置稍麻烦,但连上后都一样。

核心操作清单:
  • dbConnect() – 建立连接
  • dbListTables() – 看有哪些表
  • dbGetQuery() – 执行SQL并返回数据框
  • dbWriteTable() – 把R数据框写入数据库
  • dbDisconnect() – 用完必须关,不然连接池爆了

为什么会强调关连接?我曾经在批量建知识图谱关系时,开了100个连接没关,DBA直接打电话骂人……从那以后我都在on.exit()里写释放。

3.4 知识图谱导入场景:从文件到图数据库

你注意,本章讲的是“数据导入导出”,但最终目标是给知识图谱喂数据。通常流程是这样:

  1. 从CSV/Excel读取原始药物数据(药品名、ATC代码、适应症等)
  2. 清洗、合并、标注
  3. 写入关系型数据库或直接生成节点/边文件
  4. 用图数据库(Neo4j等)的LOAD CSV命令导入

R在这里的角色就是“ETL管道”。你想想看,你手上几百万行的Excel,人工转成CSV再手动导入,效率太低了。R一条命令搞定。

R语言数据导入导出流程(药物知识图谱) CSV文件 Excel文件 数据库 R 处理(清洗/转换) 节点/边CSV 关系型数据库 图数据库
实践建议:如果数据量大,别用Excel直接操作。我试过用openxlsx写20万行,爆内存了。最后换成fwrite写CSV,再fread读回去,稳得很。

3.5 避坑指南(我踩过的雷)

  • 字符编码:Windows默认GBK,R读入后中文乱码。解决办法:fread(encoding = "UTF-8"),或者先转成UTF-8再操作。
  • 小数点分隔符:欧洲的CSV用逗号当小数点。记得dec = ","。
  • 数据库连接池:千万别在循环里反复dbConnect和dbDisconnect。建一次连接,复用到底。
  • Excel最大行数:Excel 2007+ 支持104万行,但readxl不会报错,只会读取前几行?其实它会读全部。但文件本身超过200MB时,先剪切成多个Sheet再处理。