You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在data.table::fwrite中设置sep2参数实现列内值无分隔输出

问题说明

调用data.table::fwrite写入数据时,需要实现list类型列的内部值之间无分隔符,使用如下示例代码时触发报错:

library("data.table")
geno <- data.table(
  IID = 1:10,
  SNP = lapply(1:10, function(i) sample(0:2, 10, replace = TRUE))
)
fwrite(geno, "Geno.txt", col.names = FALSE, sep = " ", sep2 = c("","",""))

报错信息如下:

Error in fwrite(geno, "Geno.txt", col.names = FALSE, row.names = FALSE,  : 
  is.character(sep2) && length(sep2) == 3L && nchar(sep2[2L]) ==  .... is not TRUE

期望输出格式为每行两列,第一列为IID值,第二列为SNP列所有内部值拼接成的无分隔字符串,两列之间用空格分隔,且不需要提前手动修改原始数据集折叠列值:

1 2221210202
2 0020010221
3 1010022212
4 0120121221
5 1212211202
6 2100002010
7 1110011210
8 1212012121
9 2221121021
10 1122220101
报错原因

fwrite的sep2参数针对list类型列设计,固定要求为长度3的字符向量,其中第二个元素(list列内部元素的分隔符)字符长度必须≥1,传入空字符串会直接触发参数校验报错,无法通过设置sep2直接实现list列内部无分隔符的效果。

解决方案

推荐使用临时列转换的方式实现,全程不会修改原始geno对象,不需要提前折叠保存列值,性能优异:

fwrite(
  # 仅在写入时临时拼接SNP列,不改动原数据
  x = geno[, .(IID, SNP = vapply(SNP, paste, collapse = "", FUN.VALUE = character(1)))],
  file = "Geno.txt",
  col.names = FALSE,
  sep = " "
)
  • vapply遍历SNP列的每个list元素,直接拼接为无分隔的字符串,仅在写入的临时data.table中生效,原始geno的SNP列仍保留list格式
  • 该方法无外部依赖,跨Windows、macOS、Linux系统通用,即使是十万到百万行规模的数据集,拼接和写入速度都非常快

如果不想做R层面的列转换,也可以使用特殊分隔符+写入后替换的方案,适合超大规模数据集场景:

# 选用普通文本数据几乎不可能出现的控制符\x01作为list列内部分隔符
fwrite(
  geno,
  file = "Geno.txt.tmp",
  col.names = FALSE,
  sep = " ",
  sep2 = c("", "\x01", "")
)

# 调用系统命令替换掉临时文件中的特殊分隔符,输出最终文件
if (.Platform$OS.type == "unix") {
  system("sed 's/\\x01//g' Geno.txt.tmp > Geno.txt")
} else {
  system("powershell -Command \"Get-Content Geno.txt.tmp | ForEach-Object { $_ -replace [char]1, '' } | Set-Content Geno.txt\"")
}

# 清理临时文件
unlink("Geno.txt.tmp")

内容的提问来源于stack exchange,提问作者Fernando Brito Lopes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:39:17